summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock468
-rw-r--r--Cargo.toml9
-rw-r--r--build.rs8
-rw-r--r--src/commandline.lalrpop66
-rw-r--r--src/error.rs42
-rw-r--r--src/main.rs106
-rw-r--r--src/path.rs319
-rw-r--r--src/path/error.rs79
-rw-r--r--src/path/parser.lalrpop92
-rw-r--r--src/path/prelude.rs5
10 files changed, 16 insertions, 1178 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 66608c8..d6617b8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,45 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-[[package]]
-name = "aho-corasick"
-version = "0.7.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "arrayref"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
-
-[[package]]
-name = "arrayvec"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
-
-[[package]]
-name = "ascii-canvas"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29"
-dependencies = [
- "term",
-]
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
+version = 3
 
 [[package]]
 name = "autocfg"
@@ -48,77 +9,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
 [[package]]
-name = "base64"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
-
-[[package]]
-name = "bit-set"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
-dependencies = [
- "bit-vec",
-]
-
-[[package]]
-name = "bit-vec"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
-
-[[package]]
 name = "bitflags"
 version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
-name = "blake2b_simd"
-version = "0.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
-dependencies = [
- "arrayref",
- "arrayvec",
- "constant_time_eq",
-]
-
-[[package]]
-name = "block-buffer"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
-dependencies = [
- "block-padding",
- "byte-tools",
- "byteorder",
- "generic-array",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
-dependencies = [
- "byte-tools",
-]
-
-[[package]]
-name = "byte-tools"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
-
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
-[[package]]
 name = "bytes"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -143,114 +39,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
-name = "constant_time_eq"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
-dependencies = [
- "autocfg",
- "cfg-if 0.1.10",
- "lazy_static",
-]
-
-[[package]]
-name = "diff"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
-
-[[package]]
-name = "digest"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "dirs"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
-dependencies = [
- "libc",
- "redox_users",
- "winapi",
-]
-
-[[package]]
-name = "docopt"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
-dependencies = [
- "lazy_static",
- "regex",
- "serde",
- "strsim",
-]
-
-[[package]]
-name = "either"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
-
-[[package]]
-name = "ena"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
-dependencies = [
- "log",
-]
-
-[[package]]
-name = "fake-simd"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-
-[[package]]
-name = "fixedbitset"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
-
-[[package]]
-name = "generic-array"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
-dependencies = [
- "typenum",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
-
-[[package]]
 name = "hermit-abi"
 version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -260,16 +48,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "indexmap"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
-dependencies = [
- "autocfg",
- "hashbrown",
-]
-
-[[package]]
 name = "instant"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -279,61 +57,22 @@ dependencies = [
 ]
 
 [[package]]
-name = "itertools"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "lalrpop"
-version = "0.19.1"
+name = "libc"
+version = "0.2.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60fb56191fb8ed5311597e5750debe6779c9fdb487dbaa5ff302592897d7a2c8"
-dependencies = [
- "ascii-canvas",
- "atty",
- "bit-set",
- "diff",
- "docopt",
- "ena",
- "itertools",
- "lalrpop-util",
- "petgraph",
- "regex",
- "regex-syntax",
- "serde",
- "serde_derive",
- "sha2",
- "string_cache",
- "term",
- "unicode-xid",
-]
+checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
 
 [[package]]
-name = "lalrpop-util"
-version = "0.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6771161eff561647fad8bb7e745e002c304864fb8f436b52b30acda51fca4408"
+name = "line-input"
+version = "0.1.0"
 dependencies = [
- "regex",
+ "nix",
+ "pin-project",
+ "pin-utils",
+ "tokio",
 ]
 
 [[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.95"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
-
-[[package]]
 name = "lock_api"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -380,12 +119,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "new_debug_unreachable"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
-
-[[package]]
 name = "nix"
 version = "0.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -423,12 +156,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
 
 [[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
-[[package]]
 name = "parking_lot"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -448,31 +175,12 @@ dependencies = [
  "cfg-if 1.0.0",
  "instant",
  "libc",
- "redox_syscall 0.2.8",
+ "redox_syscall",
  "smallvec",
  "winapi",
 ]
 
 [[package]]
-name = "petgraph"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
-dependencies = [
- "fixedbitset",
- "indexmap",
-]
-
-[[package]]
-name = "phf_shared"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
-dependencies = [
- "siphasher",
-]
-
-[[package]]
 name = "pin-project"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -505,12 +213,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
-name = "precomputed-hash"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
-
-[[package]]
 name = "proc-macro2"
 version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -530,12 +232,6 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.57"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
-
-[[package]]
-name = "redox_syscall"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
@@ -544,97 +240,12 @@ dependencies = [
 ]
 
 [[package]]
-name = "redox_users"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
-dependencies = [
- "getrandom",
- "redox_syscall 0.1.57",
- "rust-argon2",
-]
-
-[[package]]
-name = "regex"
-version = "1.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
- "thread_local",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
-
-[[package]]
-name = "rust-argon2"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
-dependencies = [
- "base64",
- "blake2b_simd",
- "constant_time_eq",
- "crossbeam-utils",
-]
-
-[[package]]
 name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
-name = "serde"
-version = "1.0.115"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.115"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "sha2"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
-dependencies = [
- "block-buffer",
- "digest",
- "fake-simd",
- "opaque-debug",
-]
-
-[[package]]
-name = "shell"
-version = "0.1.0"
-dependencies = [
- "lalrpop",
- "lalrpop-util",
- "nix",
- "pin-project",
- "pin-utils",
- "tokio",
-]
-
-[[package]]
 name = "signal-hook-registry"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -644,37 +255,12 @@ dependencies = [
 ]
 
 [[package]]
-name = "siphasher"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
-
-[[package]]
 name = "smallvec"
 version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
 
 [[package]]
-name = "string_cache"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a"
-dependencies = [
- "lazy_static",
- "new_debug_unreachable",
- "phf_shared",
- "precomputed-hash",
- "serde",
-]
-
-[[package]]
-name = "strsim"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
-
-[[package]]
 name = "syn"
 version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -686,26 +272,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "term"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
-dependencies = [
- "byteorder",
- "dirs",
- "winapi",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
 name = "tokio"
 version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -737,24 +303,12 @@ dependencies = [
 ]
 
 [[package]]
-name = "typenum"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
-
-[[package]]
 name = "unicode-xid"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
 
 [[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index a366077..21e43da 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,12 +1,12 @@
-[lib]
+[package]
 name = "line-input"
 version = "0.1.0"
 authors = ["Irene Knapp <ireneista@gmail.com>"]
-edition = "2018"
+edition = "2021"
+publish = false
 
 [dependencies]
 #futures = "0.3"
-lalrpop-util = "0.19"
 nix = "0.19"
 pin-project = "1.0.4"
 pin-utils = "0.1.0"
@@ -14,6 +14,3 @@ pin-utils = "0.1.0"
 [dependencies.tokio]
 version = "1.6.1"
 features = [ "full" ]
-
-[build-dependencies]
-lalrpop = { version = "0.19", features = [ "lexer" ] }
diff --git a/build.rs b/build.rs
deleted file mode 100644
index 84151bf..0000000
--- a/build.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-extern crate lalrpop;
-
-fn main() {
-  let mut lalrpop = lalrpop::Configuration::new();
-  lalrpop.emit_rerun_directives(true);
-  lalrpop.use_cargo_dir_conventions();
-  lalrpop.process().unwrap();
-}
diff --git a/src/commandline.lalrpop b/src/commandline.lalrpop
deleted file mode 100644
index d52e741..0000000
--- a/src/commandline.lalrpop
+++ /dev/null
@@ -1,66 +0,0 @@
-grammar;
-
-pub Invocation: Vec<&'input str> = {
-  <WORD*>,
-};
-
-// Several of the regexps below make use of Unicode character classes. [1] is
-// the official reference to Unicode classes, and [2] is a site that is useful
-// for browsing to get an intuitive idea of what the classes mean.
-//
-// In maintaining these regexps, it's important to understand the structure
-// of Unicode character classes. There are seven top-level categories, each
-// with a single-character name (ie. "Z" for separators). Each top-level
-// category has several subcategories which form an exhaustive partition of it;
-// the subcategories have two-character names (ie. "Zs" for space separators).
-// Every allocated codepoint is in exactly one top-level category and exactly
-// one subcategory.
-//
-// It is important that these regexps exhaustively cover the entirety of
-// Unicode, without omission; otherwise lalrpop's lexer will give InvalidToken
-// errors for unrecognized characters. Overlaps will be less catastrophic, as
-// they'll be resoved by the precedence rules, but for clarity's sake they
-// should be avoided.
-//
-// [1] http://www.unicode.org/reports/tr44/#General_Category_Values
-// [2] https://www.compart.com/en/unicode/category
-//
-match {
-  // Zs is the Unicode class for space separators. This includes the ASCII
-  // space character.
-  //
-  r"\p{Zs}+" => { },
-
-  // Zl is the Unicode class for line separators. Zp is the Unicode class for
-  // paragraph separators. Newline and carriage return are included individually
-  // here, since Unicode classifies them with the control characters rather than
-  // with the space characters.
-  //
-  r"[\p{Zl}\p{Zp}\n\r]" => NEWLINE,
-
-  // This one recognizes exactly one character, the old-school double-quote. As
-  // tempting as it is to do something clever with character classes, shells have
-  // a long history of quoting syntaxes which are subtle and quick to anger, and
-  // for this project the decision is to be radically simple instead.
-  r#"["]"# => QUOTE,
-
-  // This one matches any control character other than line feed and carriage
-  // return. The grammar doesn't reference control characters, but having a
-  // token for them makes the error messages more informative.
-  r"[\p{C}&&[^\n\r]]" => CONTROL,
-
-  // Z is the unicode class for separators, which is exhaustively partitioned
-  // into line, paragraph, and space separators. Each of those subclasses is
-  // handled above. C is the class for control characters. This regexp tests
-  // for the intersection of the negation of these character classes, along
-  // with a negated class enumerating all the explicitly-recognized characters,
-  // which means it matches any character NOT in the regexps above.
-  //
-  // Note that, counterintuitively, line feed and carriage return are classified
-  // as control characters, not as line separators. Either way, this regexp would
-  // still exclude them, but the difference might be relevant when maintaining
-  // it.
-  //
-  r#"[\P{Z}&&\P{C}&&[^"]]+"# => WORD,
-}
-
diff --git a/src/error.rs b/src/error.rs
index 1d291ed..426ebf5 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,21 +1,11 @@
 #![forbid(unsafe_code)]
 
-use crate::path::GenericPath;
-use crate::path::error::{FileNameError, DirectoryNameError, PathError};
 use crate::terminal::error::TerminalError;
 
 
-type ParseError<'a> =
-  lalrpop_util::ParseError<usize, lalrpop_util::lexer::Token<'a>, &'a str>;
-
 #[derive(Debug)]
 pub enum Error {
   IO(std::io::Error),
-  Parse(String),
-  FileName(FileNameError),
-  DirectoryName(DirectoryNameError),
-  Path(PathError),
-  PathEmpiricallyFile(GenericPath),
   Terminal(TerminalError),
 }
 
@@ -25,14 +15,6 @@ impl std::fmt::Display for Error {
   fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     match self {
       Error::IO(e) => e.fmt(f),
-      Error::Parse(e) => e.fmt(f),
-      Error::FileName(e) => e.fmt(f),
-      Error::DirectoryName(e) => e.fmt(f),
-      Error::Path(e) => e.fmt(f),
-      Error::PathEmpiricallyFile(path) =>
-        f.write_fmt(format_args!(
-            "There's a file at {}, not a directory.",
-            path)),
       Error::Terminal(e) => e.fmt(f),
     }
   }
@@ -50,30 +32,6 @@ impl From<std::io::Error> for Error {
   }
 }
 
-impl From<ParseError<'_>> for Error {
-  fn from(e: ParseError<'_>) -> Error {
-    Error::Parse(format!("{}", e))
-  }
-}
-
-impl From<FileNameError> for Error {
-  fn from(e: FileNameError) -> Error {
-    Error::FileName(e)
-  }
-}
-
-impl From<DirectoryNameError> for Error {
-  fn from(e: DirectoryNameError) -> Error {
-    Error::DirectoryName(e)
-  }
-}
-
-impl From<PathError> for Error {
-  fn from(e: PathError) -> Error {
-    Error::Path(e)
-  }
-}
-
 impl From<TerminalError> for Error {
   fn from(e: TerminalError) -> Error {
     Error::Terminal(e)
diff --git a/src/main.rs b/src/main.rs
index e94ce0c..9d8ed49 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,18 +2,10 @@
 use crate::result::Result;
 use crate::terminal::{Input, Terminal};
 
-use std::collections::HashMap;
-use std::collections::HashSet;
-use std::env;
-use std::os::unix::fs::PermissionsExt;
-use std::process::{self, Command};
+use std::process;
 use tokio::io::{self, AsyncWriteExt};
 
-#[macro_use] extern crate lalrpop_util;
-
-lalrpop_mod!(pub commandline);
 pub mod error;
-pub mod path;
 pub mod result;
 pub mod terminal;
 
@@ -67,101 +59,7 @@ async fn prompt() -> Result<()> {
 }
 
 
-async fn execute(input: &str) -> Result<()> {
-  let invocation = commandline::InvocationParser::new().parse(input)?;
-
-  match invocation.as_slice() {
-    ["environment", ..] => {
-      let environment = read_environment()?;
-      println!("{:?}", environment);
-    }
-    ["which", command_name, ..] => {
-      match find_executable_path(command_name)? {
-        Some(executable_path) => {
-          println!("{}", executable_path);
-        }
-        None => {
-          println!("Command not found: {}", command_name);
-        }
-      };
-    },
-    [command_name, ..] => {
-      match find_executable_path(command_name)? {
-        Some(executable_path) => {
-          let mut command = Command::new(executable_path.to_sys_path());
-
-          let arguments = &invocation[1..];
-          command.args(arguments);
-
-          let _status = command.status()?;
-        }
-        None => {
-          println!("Command not found: {}", command_name);
-        }
-      };
-    },
-    _ => {
-      println!("invocation '{:?}'", invocation);
-    }
-  }
-
+async fn execute(_input: &str) -> Result<()> {
   Ok(())
 }
 
-
-fn read_environment() -> Result<HashMap<String,String>> {
-  Ok(env::vars().collect())
-}
-
-
-fn get_environment(variable_name: &str) -> Result<Option<String>> {
-  Ok(env::vars()
-     .find(|(key, _)| key == variable_name)
-     .map(|(_, value)| value))
-}
-
-
-fn get_search_paths() -> Result<Vec<path::AbsoluteDirectoryPath>> {
-  let paths = get_environment("PATH")?.unwrap_or_default();
-  let paths = path::parse_path_list(&paths)?;
-
-  let mut result = Vec::new();
-  let mut seen = HashSet::new();
-  for path in paths {
-    if seen.contains(&path) {
-      continue;
-    }
-
-    seen.insert(path.clone());
-    result.push(path);
-  }
-
-  Ok(result)
-}
-
-
-fn find_executable_path(command_name: &str)
-  -> Result<Option<path::AbsoluteFilePath>>
-{
-  let file_name: path::FileName = command_name.parse()?;
-  let search_paths = get_search_paths()?;
-
-  let mut executable_path: Option<path::AbsoluteFilePath> = None;
-  for search_path in &search_paths {
-    let candidate_path = search_path.concat_file_name(&file_name);
-    match candidate_path.to_sys_path().metadata() {
-      Ok(metadata) => {
-        if metadata.is_file()
-          && metadata.permissions().mode() & 0o111 != 0
-        {
-          executable_path = Some(candidate_path);
-          break;
-        }
-      },
-      Err(_) => { },
-    }
-  }
-
-  Ok(executable_path)
-}
-
diff --git a/src/path.rs b/src/path.rs
deleted file mode 100644
index 7df10b2..0000000
--- a/src/path.rs
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- *   We implement most aspects of paths independently, not relying on
- * std::path, on the theory that path syntax is such an important part of a
- * shell that it doesn't make sense to try to integrate with non-Unix syntaxes.
- * However, we do use std::path to print individual path components, in order
- * to get the benefit of its functionality for handling non-Unicode filenames.
- */
-
-#![forbid(unsafe_code)]
-use crate::path::prelude::*;
-
-use std::str::FromStr;
-
-
-lalrpop_mod!(pub parser, "/path/parser.rs");
-pub mod error;
-pub mod prelude;
-
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub struct AbsoluteDirectoryPath {
-  directory_names: Vec<DirectoryName>,
-}
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub struct AbsoluteFilePath {
-  directory_names: Vec<DirectoryName>,
-  file_name: FileName,
-}
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub struct FileName(String);
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub struct DirectoryName(String);
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub struct GenericPath {
-  components: Vec<GenericPathComponent>,
-  starts_with_slash: bool,
-  ends_with_slash: bool,
-}
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub enum GenericPathComponent {
-  FileOrDirectoryName(String),
-  CurrentDirectory,
-  ParentDirectory,
-}
-
-
-impl std::fmt::Display for AbsoluteDirectoryPath {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    for directory_name in &self.directory_names {
-      f.write_str("/")?;
-      directory_name.fmt(f)?;
-    }
-
-    f.write_str("/")?;
-
-    Ok(())
-  }
-}
-
-
-impl std::fmt::Display for AbsoluteFilePath {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    for directory_name in &self.directory_names {
-      f.write_str("/")?;
-      directory_name.fmt(f)?;
-    }
-
-    f.write_str("/")?;
-
-    self.file_name.fmt(f)?;
-
-    Ok(())
-  }
-}
-
-
-impl std::fmt::Display for FileName {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    match self {
-      FileName(name) => {
-        let std_path = std::path::Path::new(&name);
-        f.write_fmt(format_args!("{}", std_path.display()))?;
-      },
-    }
-
-    Ok(())
-  }
-}
-
-
-impl std::fmt::Display for DirectoryName {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    match self {
-      DirectoryName(name) => {
-        let std_path = std::path::Path::new(&name);
-        f.write_fmt(format_args!("{}", std_path.display()))?;
-      },
-    }
-
-    Ok(())
-  }
-}
-
-
-impl std::fmt::Display for GenericPath {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    if self.starts_with_slash {
-      f.write_str("/")?;
-    }
-
-    let mut is_first = true;
-    for component in &self.components {
-      if !is_first {
-        f.write_str("/")?;
-      }
-
-      component.fmt(f)?;
-
-      is_first = false;
-    }
-
-    if self.ends_with_slash {
-      f.write_str("/")?;
-    }
-
-    Ok(())
-  }
-}
-
-
-impl std::fmt::Display for GenericPathComponent {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    match self {
-      GenericPathComponent::FileOrDirectoryName(name) => {
-        let std_path = std::path::Path::new(&name);
-        f.write_fmt(format_args!("{}", std_path.display()))?;
-      },
-      GenericPathComponent::CurrentDirectory => {
-        f.write_str(".")?;
-      },
-      GenericPathComponent::ParentDirectory => {
-        f.write_str("..")?;
-      },
-    }
-
-    Ok(())
-  }
-}
-
-
-impl FromStr for FileName {
-  type Err = FileNameError;
-
-  fn from_str(input: &str) -> std::result::Result<Self, Self::Err> {
-    if input.find('/').is_some() {
-      Err(FileNameError::ContainsSlash(input.to_string()))
-    } else {
-      Ok(FileName(input.to_string()))
-    }
-  }
-}
-
-
-impl FromStr for DirectoryName {
-  type Err = DirectoryNameError;
-
-  fn from_str(input: &str) -> std::result::Result<Self, Self::Err> {
-    if input.find('/').is_some() {
-      Err(DirectoryNameError::ContainsSlash(input.to_string()))
-    } else {
-      Ok(DirectoryName(input.to_string()))
-    }
-  }
-}
-
-
-impl FromStr for GenericPathComponent {
-  type Err = PathError;
-
-  fn from_str(input: &str) -> std::result::Result<Self, Self::Err> {
-    parser::PathComponentParser::new().parse(input).map_err(
-        |e| PathError::Parse(e.to_string()))
-  }
-}
-
-
-impl AbsoluteDirectoryPath {
-  pub fn to_sys_path(&self) -> std::path::PathBuf {
-    let mut result = std::path::PathBuf::new();
-    result.push(format!("{}", self));
-    result
-  }
-
-  pub fn concat_file_name(&self, file_name: &FileName) -> AbsoluteFilePath {
-    AbsoluteFilePath {
-      directory_names: self.directory_names.clone(),
-      file_name: file_name.clone(),
-    }
-  }
-}
-
-
-impl AbsoluteFilePath {
-  pub fn to_sys_path(&self) -> std::path::PathBuf {
-    let mut result = std::path::PathBuf::new();
-    result.push(format!("{}", self));
-    result
-  }
-}
-
-
-pub fn parse_path_list(path_list: &str)
-  -> Result<Vec<AbsoluteDirectoryPath>>
-{
-  match parser::PathListParser::new().parse(path_list) {
-    Ok(parsed_paths) => {
-      let mut result = Vec::new();
-      for generic_path in parsed_paths {
-        let path = absolute_directory_path(generic_path)?;
-        result.push(path);
-      }
-      Ok(result)
-    },
-   Err(original_error) => {
-      match parser::PathListAllowingEmptyPathsParser::new()
-        .parse(path_list)
-      {
-        Ok(_) => {
-          Err(PathError::PathListHasEmptyComponents(path_list.to_string()))
-        },
-        Err(_) => {
-          Err(PathError::Parse(original_error.to_string()))
-        },
-      }
-    },
-  }
-}
-
-
-pub fn absolute_directory_path(generic_path: GenericPath)
-  -> Result<AbsoluteDirectoryPath>
-{
-  if !generic_path.starts_with_slash {
-    return Err(PathError::PathLexicallyRelative(generic_path));
-  }
-
-  let mut flattened_components = Vec::new();
-  for component in &generic_path.components {
-    match component {
-      GenericPathComponent::CurrentDirectory => { },
-      GenericPathComponent::ParentDirectory => {
-        if flattened_components.len() > 0 {
-          flattened_components.pop();
-        } else {
-          return Err(PathError::PathLexicallyInvalid(generic_path));
-        }
-      },
-      GenericPathComponent::FileOrDirectoryName(name) => {
-        flattened_components.push(DirectoryName(name.to_string()));
-      },
-    }
-  }
-
-  Ok(AbsoluteDirectoryPath {
-    directory_names: flattened_components,
-  })
-}
-
-
-pub fn absolute_file_path(generic_path: GenericPath)
-  -> Result<AbsoluteFilePath>
-{
-  if !generic_path.starts_with_slash {
-    return Err(PathError::PathLexicallyRelative(generic_path));
-  }
-
-  if generic_path.ends_with_slash {
-    return Err(PathError::PathLexicallyDirectory(generic_path));
-  }
-
-  let mut iterator = generic_path.components.iter();
-
-  let file_name = match iterator.next_back() {
-    Some(GenericPathComponent::FileOrDirectoryName(name)) => {
-      FileName(name.to_string())
-    }
-    _ => {
-      return Err(PathError::PathLexicallyInvalid(generic_path));
-    }
-  };
-
-  let mut flattened_components = Vec::new();
-  for component in &generic_path.components {
-    match component {
-      GenericPathComponent::CurrentDirectory => { },
-      GenericPathComponent::ParentDirectory => {
-        if flattened_components.len() > 0 {
-          flattened_components.pop();
-        } else {
-          return Err(PathError::PathLexicallyInvalid(generic_path));
-        }
-      },
-      GenericPathComponent::FileOrDirectoryName(name) => {
-        flattened_components.push(DirectoryName(name.to_string()));
-      },
-    }
-  }
-
-  Ok(AbsoluteFilePath {
-    directory_names: flattened_components,
-    file_name: file_name,
-  })
-}
-
diff --git a/src/path/error.rs b/src/path/error.rs
deleted file mode 100644
index aee6e9f..0000000
--- a/src/path/error.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-#![forbid(unsafe_code)]
-
-use crate::path::GenericPath;
-
-pub type Result<T> = std::result::Result<T, PathError>;
-
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub enum FileNameError {
-  ContainsSlash(String),
-}
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub enum DirectoryNameError {
-  ContainsSlash(String),
-}
-
-#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)]
-pub enum PathError {
-  Parse(String),
-  PathLexicallyDirectory(GenericPath),
-  PathLexicallyRelative(GenericPath),
-  PathLexicallyInvalid(GenericPath),
-  PathListHasEmptyComponents(String),
-}
-
-
-impl std::error::Error for FileNameError { }
-
-impl std::error::Error for DirectoryNameError { }
-
-impl std::error::Error for PathError { }
-
-impl std::fmt::Display for FileNameError {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    match self {
-      FileNameError::ContainsSlash(s) =>
-        f.write_fmt(format_args!(
-            "File names cannot contain slashes, but {:?} does.", s)),
-    }
-  }
-}
-
-impl std::fmt::Display for DirectoryNameError {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    match self {
-      DirectoryNameError::ContainsSlash(s) =>
-        f.write_fmt(format_args!(
-            "File names cannot contain slashes, but {:?} does.", s)),
-    }
-  }
-}
-
-impl std::fmt::Display for PathError {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    match self {
-      PathError::Parse(s) =>
-        f.write_fmt(format_args!("Syntax error in path: {}", s)),
-      PathError::PathLexicallyDirectory(path) =>
-        f.write_fmt(format_args!(
-            "The path {} ends in a slash, but is supposed to refer to a file, \
-             not a directory.",
-            path)),
-      PathError::PathLexicallyRelative(path) =>
-        f.write_fmt(format_args!(
-            "The path {} is relative, not absolute.",
-            path)),
-      PathError::PathLexicallyInvalid(path) =>
-        f.write_fmt(format_args!(
-            "This isn't a valid path. {}",
-            path)),
-      PathError::PathListHasEmptyComponents(path_list) =>
-        f.write_fmt(format_args!(
-            "Path list has empty components: {}",
-            path_list)),
-    }
-  }
-}
-
diff --git a/src/path/parser.lalrpop b/src/path/parser.lalrpop
deleted file mode 100644
index c41b3fd..0000000
--- a/src/path/parser.lalrpop
+++ /dev/null
@@ -1,92 +0,0 @@
-grammar;
-
-use crate::path::GenericPath;
-use crate::path::GenericPathComponent;
-
-pub PathList: Vec<GenericPath> = {
-  => {
-    Vec::new()
-  },
-  <mut left:(<PathNoColons> COLON)*> <right:PathNoColons> => {
-    left.push(right);
-    left
-  },
-};
-
-pub PathListAllowingEmptyPaths: Vec<GenericPath> = {
-  => vec![GenericPath {
-    components: Vec::new(),
-    starts_with_slash: false,
-    ends_with_slash: false,
-  }],
-  PathNoColons => vec![<>],
-  <mut left:PathListAllowingEmptyPaths> COLON => {
-    left.push(GenericPath {
-      components: Vec::new(),
-      starts_with_slash: false,
-      ends_with_slash: false,
-    });
-    left
-  },
-  <mut left:PathListAllowingEmptyPaths> COLON <right:PathNoColons> => {
-    left.push(right);
-    left
-  },
-}
-
-pub PathNoColons: GenericPath = {
-  SLASH => GenericPath {
-    components: Vec::new(),
-    starts_with_slash: true,
-    ends_with_slash: true,
-  },
-  <PathNoColons2> => GenericPath {
-    components: <>,
-    starts_with_slash: false,
-    ends_with_slash: false,
-  },
-  <PathNoColons2> SLASH => GenericPath {
-    components: <>,
-    starts_with_slash: false,
-    ends_with_slash: true,
-  },
-  SLASH <PathNoColons2> => GenericPath {
-    components: <>,
-    starts_with_slash: true,
-    ends_with_slash: false,
-  },
-  SLASH <PathNoColons2> SLASH => GenericPath {
-    components: <>,
-    starts_with_slash: true,
-    ends_with_slash: true,
-  },
-}
-
-PathNoColons2: Vec<GenericPathComponent> = {
-  <PathComponent> => vec![<>],
-  <mut left:PathNoColons2> SLASH <right:PathComponent> => {
-    left.push(right);
-    left
-  }
-}
-
-pub PathComponent: GenericPathComponent = {
-  DOT => GenericPathComponent::CurrentDirectory,
-  DOT_DOT => GenericPathComponent::ParentDirectory,
-  <PATH_COMPONENT_NO_COLONS> =>
-    GenericPathComponent::FileOrDirectoryName(<>.to_string())
-}
-
-// Whitespace is not allowed.
-match {
-  r"[^:/]+" => PATH_COMPONENT_NO_COLONS,
-
-  r"/" => SLASH,
-
-  ":" => COLON,
-
-  "." => DOT,
-
-  ".." => DOT_DOT,
-}
-
diff --git a/src/path/prelude.rs b/src/path/prelude.rs
deleted file mode 100644
index f7b23dd..0000000
--- a/src/path/prelude.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![forbid(unsafe_code)]
-
-pub use crate::path::error::{
-    Result, DirectoryNameError, FileNameError, PathError};
-