diff options
| author | Nathan Perry <avaglir@gmail.com> | 2019-03-29 15:20:27 -0400 |
|---|---|---|
| committer | Nathan Perry <avaglir@gmail.com> | 2019-03-29 15:20:27 -0400 |
| commit | 5f63ea4a1991159348c2e7d7f519c3ac6cd46454 (patch) | |
| tree | 4af4ba0814287dd4ce6e7144c614f7def495c162 | |
| parent | 2685e6028dd775bcd618a3d8d2b22e32730454a3 (diff) | |
switch over to pest
| -rw-r--r-- | Cargo.lock | 132 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/commands/calc.pest | 79 | ||||
| -rw-r--r-- | src/commands/mod.rs | 5 | ||||
| -rw-r--r-- | src/commands/roll.rs | 422 | ||||
| -rw-r--r-- | src/main.rs | 3 |
6 files changed, 333 insertions, 311 deletions
@@ -43,6 +43,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "arrayref" +version = "0.3.5" +source = "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" @@ -138,11 +143,25 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "build_const" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "byte-tools" +version = "0.2.0" +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" @@ -330,6 +349,14 @@ dependencies = [ ] [[package]] +name = "digest" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "dotenv" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -437,6 +464,11 @@ dependencies = [ ] [[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "fern" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -508,6 +540,14 @@ dependencies = [ ] [[package]] +name = "generic-array" +version = "0.9.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 = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -749,6 +789,11 @@ dependencies = [ ] [[package]] +name = "maplit" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -941,15 +986,6 @@ dependencies = [ ] [[package]] -name = "nom" -version = "4.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1086,6 +1122,45 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "pest" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_generator" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_meta" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "phf" version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1574,6 +1649,17 @@ dependencies = [ ] [[package]] +name = "sha-1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "sha1" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1766,7 +1852,8 @@ dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1936,6 +2023,16 @@ dependencies = [ ] [[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-trie" +version = "0.1.1" +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" @@ -2131,6 +2228,7 @@ dependencies = [ "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "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" @@ -2141,7 +2239,9 @@ dependencies = [ "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" @@ -2163,6 +2263,7 @@ dependencies = [ "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" "checksum diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a2469cbcf1dfb9446e491cac4c493c2554133f87f7d041e892ac82e5cd36e863" "checksum diesel_derives 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62a27666098617d52c487a41f70de23d44a1dc1f3aa5877ceba2790fb1f1cab4" +"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum dotenv 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d0a1279c96732bc6800ce6337b6a614697b0e74ae058dc03c62ebeb78b4d86" "checksum dotenv 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eea1395d2df3b5344dc577809296d9578303296e8d105c408aa80ed67d598ef1" "checksum dotenv_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "106db107983c2d0c10a9601cdd0c88514df87515e18d24df87e7ae0e2a50c3fa" @@ -2174,6 +2275,7 @@ dependencies = [ "checksum evzht9h3nznqzwl 0.0.2 (git+https://github.com/mammothbane/rust-websocket)" = "<none>" "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 fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b48af88aaf938b11baef948a5599e66e709cf92854aa2b87c71f1bcf20f80a01" "checksum flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" @@ -2184,6 +2286,7 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" @@ -2210,6 +2313,7 @@ dependencies = [ "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" @@ -2230,7 +2334,6 @@ dependencies = [ "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" -"checksum nom 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4836e9d6036552017e107edc598c97b2dee245161ff1b1ad4af215004774b354" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" @@ -2247,6 +2350,10 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54f0c72a98d8ab3c99560bfd16df8059cc10e1f9a8e83e6e3b97718dd766e9c3" +"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" +"checksum pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" @@ -2301,6 +2408,7 @@ dependencies = [ "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum serenity 0.5.11 (git+https://github.com/mammothbane/serenity)" = "<none>" +"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" @@ -2339,6 +2447,8 @@ dependencies = [ "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" @@ -29,9 +29,10 @@ itertools = "^0.8" serde = { version = "~1.0", features = ["derive"] } serde_json = "~1.0" timeago = "^0.1" -nom = { version = "~4.2", features = ["verbose-errors"] } statrs = "^0.10" fnv = "~1.0" +pest = "~2.1" +pest_derive = "~2.1" [dependencies.serenity] default-features = false diff --git a/src/commands/calc.pest b/src/commands/calc.pest new file mode 100644 index 0000000..07eeddb --- /dev/null +++ b/src/commands/calc.pest @@ -0,0 +1,79 @@ +num = { + hex + | oct + | binary + | float +} + +float = @{ int ~ ( "." ~ ASCII_DIGIT*)? ~ (^"e" ~ int)? } + int = { "-"? ~ ASCII_DIGIT+ } + +hex = @{ "0x" ~ ASCII_HEX_DIGIT+ } +oct = @{ "0o" ~ ASCII_OCT_DIGIT+ } +binary = @{ "0b" ~ ASCII_BIN_DIGIT+ } + +infix = _{ add | sub | mul | div | modulo } + add = { "+" } + sub = { "-" } + modulo = { "%" | "mod" } + mul = { "*" } + div = { "/" } + +tight_infix = _{ dice | pow } + dice = { "d" } + pow = { "^" } + +trig = _{ sin | cos | tan | asin | acos | atan } + sin = { "sin" } + cos = { "cos" } + tan = { "tan" } + asin = { "asin" } + acos = { "acos" } + atan = { "atan" } + +htrig = _{ sinh | cosh | tanh | asinh | acosh | atanh } + sinh = { "sinh" } + cosh = { "cosh" } + tanh = { "tanh" } + asinh = { "asinh" } + acosh = { "acosh" } + atanh = { "atanh" } + +unary_prefix = _{ log | sqrt | sgn | htrig | trig | exp | abs | ceil | floor | round } + log = { "log" | "ln" } + sqrt = { "sqrt" } + sgn = { "sgn" } + exp = { "exp" } + abs = { "abs" } + ceil = { "ceil" } + floor = { "floor" } + round = { "round" } + +binary_prefix = _{ min | max | atan2 } + min = { "min" } + max = { "max" } + atan2 = { "atan2" } + +suffix = _{ factorial } + factorial = { "!" } + +term = _{ num | "(" ~ expr ~ ")" } + +suffix_expr = { term ~ suffix } +unary_expr = ${ unary_prefix ~ ws+ ~ outfix_expr } +binary_expr = ${ binary_prefix ~ ws+ ~ outfix_expr ~ ws+ ~ outfix_expr } + +tight = _{ (suffix_expr | term) ~ (tight_infix ~ tight)* } + +expr = { outfix_expr ~ (infix ~ outfix_expr)* } + +outfix_expr = _{ + tight | + binary_expr | + unary_expr +} + +calc = _{ SOI ~ expr ~ EOI } + +ws = _{ " " | "\t" | "\n" } +WHITESPACE = _{ ws } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 1582977..6596a32 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -60,11 +60,6 @@ pub fn register_commands(f: StandardFramework) -> StandardFramework { .desc("simulate rolling dice") .guild_only(true) .exec(roll::roll)) - .command("debug_expr", |c| c - .desc("debug calculator expression") - .owners_only(true) - .exec(roll::debug_expr) - ) .unrecognised_command(|ctx, msg, unrec| { let url = match msg.content.split_whitespace().skip(1).next() { Some(x) if x.starts_with("http") => x, diff --git a/src/commands/roll.rs b/src/commands/roll.rs index bdb729e..b447692 100644 --- a/src/commands/roll.rs +++ b/src/commands/roll.rs @@ -1,10 +1,3 @@ -use failure::Error; -use itertools::Itertools; -use nom::{ - self, - double, - types::CompleteStr, -}; use rand::prelude::*; use serenity::{ framework::standard::Args, @@ -18,334 +11,177 @@ use crate::{ Result, }; -#[derive(Clone, Debug, PartialEq)] -enum CalcExpr { - Binary(BinOp, Box<CalcExpr>, Box<CalcExpr>), - Unary(UnaryOp, Box<CalcExpr>), - Term(f64), -} - -#[derive(Clone, Debug, PartialEq, Fail)] -enum CalcParseError { - #[fail(display = "couldn't consume entire expression. parsed: {:?}, remaining: '{}'.", parsed, remaining)] - NotReadToEnd { - parsed: Box<CalcExpr>, - remaining: String, - }, - #[fail(display = "nom error: {}", _0)] - Nom(String), -} +#[derive(Parser)] +#[grammar = "commands/calc.pest"] +struct Calc; -impl CalcExpr { - pub fn parse<S: AsRef<str>>(input: S) -> Result<Box<Self>> { - parse_expr(CompleteStr(input.as_ref())) - .map_err(|e| CalcParseError::Nom(format!("{}", e))) - .and_then(|(s, res)| { - if s.len() != 0 { - Err(CalcParseError::NotReadToEnd { - parsed: res, - remaining: s.as_ref().to_owned(), - }) - } else { - Ok(res) - } - }) - .map_err(Error::from) - } +impl Calc { + fn eval<S: AsRef<str>>(s: S) -> Result<f64> { + use pest::{ + Parser, + prec_climber::PrecClimber, + iterators::{Pair, Pairs}, + }; - pub fn pretty(&self) -> String { - format!("```\n{}\n```", self.pretty_helper(0)) - } + use self::Rule::*; - fn pretty_helper(&self, depth: usize) -> String { - match self { - CalcExpr::Binary(op, e1, e2) => { - let lines = vec! { - format!("{}{:?} ({}) {{", "\t".repeat(depth), op, self.compute()), - e1.pretty_helper(depth + 1), - e2.pretty_helper(depth + 1), - "\t".repeat(depth) + "}", + lazy_static! { + static ref CLIMBER: PrecClimber<self::Rule> = { + use pest::prec_climber::{ + Operator, + Assoc::*, }; - lines.into_iter().join("\n") - }, - CalcExpr::Unary(op, e) => { - let lines = vec! { - format!("{}{:?} ({}) {{", "\t".repeat(depth), op, self.compute()), - e.pretty_helper(depth + 1), - "\t".repeat(depth) + "}", - }; - - lines.into_iter().join("\n") - }, - CalcExpr::Term(val) => { - format!("{}{}", "\t".repeat(depth), val) - } + PrecClimber::new(vec![ + Operator::new(add, Left) | Operator::new(sub, Left) | Operator::new(modulo, Left), + Operator::new(mul, Left) | Operator::new(div, Left), + Operator::new(dice, Left), + Operator::new(pow, Right), + ]) + }; } - } - pub fn compute(&self) -> f64 { - use self::CalcExpr::*; - use self::BinOp::*; - use self::UnaryOp::*; + let result = Calc::parse(calc, s.as_ref())?; - match self { - Binary(bop, e1, e2) => { - let r1 = e1.compute(); - let r2 = e2.compute(); - match bop { - Add => r1 + r2, - Sub => r1 - r2, - Mul => r1 * r2, - Div => r1 / r2, - Mod => r1 % r2, - Pow => r1.powf(r2), - Min => r1.min(r2), - Max => r1.max(r2), - DiceRoll => { - let dice_count = r1 as usize; - let dice_faces = r2 as usize; + fn eval_single_pair(pair: Pair<self::Rule>) -> f64 { + match pair.as_rule() { + oct | hex | binary => { + let base = match pair.as_rule() { + hex => 16, + oct => 8, + binary => 2, + _ => unreachable!(), + }; - let mut rng = thread_rng(); - (0..dice_count).map(|_| rng.gen_range(1, dice_faces + 1)).sum::<usize>() as f64 - } - } - }, - Unary(uop, e) => { - let r = e.compute(); + u64::from_str_radix(&pair.as_str()[2..], base).unwrap() as f64 + }, + float => pair.as_str().parse::<f64>().unwrap(), + expr | num => eval_expr(pair.into_inner()), + unary_expr => { + let mut p = pair.into_inner(); - match uop { - Neg => -r, - Log => r.ln(), - Sqrt => r.sqrt(), - Sgn => r.signum(), - Sin => r.sin(), - Cos => r.cos(), - Tan => r.tan(), - Factorial => statrs::function::gamma::gamma(r), - Exp => r.exp(), - Abs => r.abs(), - Ceil => r.ceil(), - Floor => r.floor(), - Round => r.round(), - } - }, - Term(v) => *v, - } - } -} + let op = p.next().unwrap(); + let arg = eval_expr(p); -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum BinOp { - Add, - Sub, - Mul, - Div, - Mod, - Pow, - Min, - Max, - DiceRoll, -} + match op.as_rule() { + log => arg.ln(), + sqrt => arg.sqrt(), + sgn => arg.signum(), -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum UnaryOp { - Log, - Sqrt, - Sgn, - Exp, - Sin, - Cos, - Tan, - Factorial, - Neg, - Ceil, - Floor, - Abs, - Round, -} + sin => arg.sin(), + cos => arg.cos(), + tan => arg.tan(), + asin => arg.asin(), + acos => arg.acos(), + atan => arg.atan(), -fn parse_expr(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, up_to_add_sub_mod) -} + sinh => arg.sinh(), + cosh => arg.cosh(), + tanh => arg.tanh(), + asinh => arg.asinh(), + acosh => arg.acosh(), + atanh => arg.atanh(), -fn parse_add_sub_mod(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - tpl: tuple!(up_to_div_mul, ws!(one_of!("+-%")), parse_expr) >> - ({ - let (expr1, op, expr2) = tpl; - let op = match op { - '+' => BinOp::Add, - '-' => BinOp::Sub, - '%' => BinOp::Mod, - _ => unreachable!(), - }; - Box::new(CalcExpr::Binary(op, expr1, expr2)) - }) - )) -} + exp => arg.exp(), + abs => arg.abs(), + ceil => arg.ceil(), + floor => arg.floor(), + round => arg.round(), + _ => unreachable!(), + } + }, + binary_expr => { + let mut p = pair.into_inner(); -fn parse_div_mul(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - tpl: tuple!(up_to_binary_prefix, ws!(one_of!("/*")), parse_expr) >> - ({ - let (expr1, op, expr2) = tpl; - let op = match op { - '*' => BinOp::Mul, - '/' => BinOp::Div, - '^' => BinOp::Pow, - _ => unreachable!(), - }; - Box::new(CalcExpr::Binary(op, expr1, expr2)) - }) - )) -} + let op = p.next().unwrap(); -fn parse_binary_prefix(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - op: ws!(alt_complete!( - tag!("min") => { |_| BinOp::Min } | - tag!("max") => { |_| BinOp::Max } - )) >> - expr1: up_to_unary_prefix >> - expr2: up_to_unary_prefix >> - (Box::new(CalcExpr::Binary(op, expr1, expr2))) - )) -} + let arg1 = eval_single_pair(p.next().unwrap()); + let arg2 = eval_single_pair(p.next().unwrap()); -fn parse_unary_prefix(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - op: ws!(alt_complete!( - tag!("log") => { |_| UnaryOp::Log } - | tag!("sqrt") => { |_| UnaryOp::Sqrt } - | tag!("sin") => { |_| UnaryOp::Sin } - | tag!("cos") => { |_| UnaryOp::Cos } - | tag!("tan") => { |_| UnaryOp::Tan } - | tag!("sgn") => { |_| UnaryOp::Sgn } - | tag!("exp") => { |_| UnaryOp::Exp } - | tag!("ceil") => { |_| UnaryOp::Ceil } - | tag!("floor") => { |_| UnaryOp::Floor } - | tag!("abs") => { |_| UnaryOp::Abs } - | tag!("round") => { |_| UnaryOp::Round } - )) >> - expr: up_to_dice >> - (Box::new(CalcExpr::Unary(op, expr))) - )) -} + assert!(p.next().is_none()); -fn parse_dice(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - tpl: separated_pair!(up_to_pow, ws!(char!('d')), up_to_pow) >> - ({ - let (expr1, expr2) = tpl; - Box::new(CalcExpr::Binary(BinOp::DiceRoll, expr1, expr2)) - }) - )) -} + match op.as_rule() { + min => arg1.min(arg2), + max => arg1.max(arg2), + atan2 => arg1.atan2(arg2), + _ => unreachable!(), + } + }, + suffix_expr => { + let mut p = pair.into_inner(); -fn parse_pow(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - tpl: separated_pair!(up_to_neg, ws!(char!('^')), up_to_neg) >> - ({ - let (expr1, expr2) = tpl; - Box::new(CalcExpr::Binary(BinOp::Pow, expr1, expr2)) - }) - )) -} + let arg = eval_expr(p.next().unwrap().into_inner()); + let op = p.next().unwrap(); -fn parse_neg(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - expr: ws!(preceded!(char!('-'), up_to_suffix)) >> - (Box::new(CalcExpr::Unary(UnaryOp::Neg, expr))) - )) -} + assert!(p.next().is_none()); -fn parse_suffix(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, do_parse!( - expr: terminated!(parse_term_or_paren, ws!(tag!("!"))) >> - (Box::new(CalcExpr::Unary(UnaryOp::Factorial, expr))) - )) -} + match op.as_rule() { + factorial => statrs::function::gamma::gamma(arg + 1.), + _ => unreachable!(), + } + }, + _ => unreachable!(), + } + } -fn parse_term_or_paren(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - ws!(input, alt_complete!( - delimited!(char!('('), parse_expr, char!(')')) | - do_parse!( - dat: double >> - (Box::new(CalcExpr::Term(dat))) - ) - )) -} + fn eval_expr(p: Pairs<self::Rule>) -> f64 { + CLIMBER.climb( + p, + eval_single_pair, + |lhs: f64, op, rhs: f64| match op.as_rule() { + add => lhs + rhs, + sub => lhs - rhs, + mul => lhs * rhs, + div => lhs / rhs, + pow => lhs.powf(rhs), + dice => { + let dice_count = lhs as usize; + let dice_faces = rhs as usize; -macro_rules! up_to { - ($up_to_name:ident, $fn_name:ident, $prev:ident) => ( - fn $up_to_name(input: CompleteStr) -> nom::IResult<CompleteStr, Box<CalcExpr>> { - alt_complete!(input, $fn_name | $prev) + let mut rng = thread_rng(); + (0..dice_count).map(|_| rng.gen_range(1, dice_faces + 1)).sum::<usize>() as f64 + }, + _ => unreachable!(), + } + ) } - ) -} -up_to! { up_to_add_sub_mod, parse_add_sub_mod, up_to_div_mul } -up_to! { up_to_div_mul, parse_div_mul, up_to_binary_prefix } -up_to! { up_to_binary_prefix, parse_binary_prefix, up_to_unary_prefix } -up_to! { up_to_unary_prefix, parse_unary_prefix, up_to_dice } -up_to! { up_to_dice, parse_dice, up_to_pow } -up_to! { up_to_pow, parse_pow, up_to_neg } -up_to! { up_to_neg, parse_neg, up_to_suffix } -up_to! { up_to_suffix, parse_suffix, parse_term_or_paren } + Ok(eval_expr(result)) + } +} #[cfg(test)] mod test { use super::*; #[test] - fn test_parse_usize() { - let (s, expr) = parse_expr("123".into()).unwrap(); - assert_eq!(s.0, ""); - assert_eq!(expr, box CalcExpr::Term(123.)); + fn test_calc_basics() { + assert_eq!(3., Calc::eval("1 + 2").unwrap()); + assert_eq!(3.0f64.ln(), Calc::eval("log 3").unwrap()); + assert!(6. - Calc::eval("3!").unwrap() < 0.0001); + assert_eq!(3., Calc::eval("max 3 2").unwrap()); } #[test] - fn test_parens() { - let (s, expr) = parse_expr("(123)".into()).unwrap(); - assert_eq!(s.0, ""); - assert_eq!(expr, box CalcExpr::Term(123.)); + fn test_binary_unary() { + assert_eq!(3.0f64.ln(), Calc::eval("max log 3 log 2").unwrap()); } #[test] - fn test_infix() { - let (s, expr) = parse_expr("1 + 2".into()).unwrap(); - assert_eq!(s.0, ""); - assert_eq!(expr, box CalcExpr::Binary(BinOp::Add, box CalcExpr::Term(1.), box CalcExpr::Term(2.))) + fn test_prefix_suffix() { + assert!(6. - Calc::eval("abs 3!").unwrap() < 0.0001); } - } pub fn roll(_ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { - match CalcExpr::parse(args.rest()) { - Ok(expr) => send(msg.channel_id, &format!("{}", expr.compute()), msg.tts), - Err(e) => { - let parse_err = e.downcast::<CalcParseError>().unwrap(); - if let CalcParseError::NotReadToEnd { remaining, .. } = parse_err { - error!("parsing '{}': failed to consume '{}'", args.rest(), remaining); - send(msg.channel_id, "I COULDN'T READ THAT YOU FUCK", msg.tts) - } else { - Err(parse_err.into()) - } + match Calc::eval(args.rest()) { + Ok(result) => { + debug!("got calc result '{}'", result); + send(msg.channel_id, &format!("{}", result), msg.tts) }, - } -} - -pub fn debug_expr(_ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { - match CalcExpr::parse(args.rest()) { - Ok(expr) => send(msg.channel_id, &expr.pretty(), false), Err(e) => { - let parse_err = e.downcast::<CalcParseError>().unwrap(); - if let CalcParseError::NotReadToEnd { remaining, parsed } = parse_err { - send(msg.channel_id, &format!("parsed this expr: {}\nwith remaining text: '{}'", parsed.pretty(), remaining), false) - } else { - Err(parse_err.into()) - } - } + error!("error encountered reading calc '{}': {}", args.rest(), e); + send(msg.channel_id, "I COULDN'T READ THAT YOU FUCK", msg.tts) + }, } } diff --git a/src/main.rs b/src/main.rs index 177f726..1d1c6dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,8 @@ extern crate fnv; #[cfg_attr(test, macro_use)] extern crate itertools; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -#[macro_use] extern crate nom; +extern crate pest; +#[macro_use] extern crate pest_derive; extern crate rand; extern crate regex; extern crate reqwest; |
