[rust] Add regex crate and its dependencies

Previously approved: OSRB-83, OSRB-80, OSRB-84, OSRB-87, OSRB-92, OSRB-100

TEXT-36: #progress

Change-Id: I76a55475224809c6f35dc0d3b7a97c88b86d3548
diff --git a/rustc_deps/Cargo.lock b/rustc_deps/Cargo.lock
index 33164c7..bc64055 100644
--- a/rustc_deps/Cargo.lock
+++ b/rustc_deps/Cargo.lock
@@ -4,6 +4,14 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "aho-corasick"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "ansi_term"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -413,6 +421,7 @@
  "pin-utils 0.1.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rust-crypto 0.2.36",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1025,6 +1034,26 @@
 ]
 
 [[package]]
+name = "regex"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.3 (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.6.3"
+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 = "remove_dir_all"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1280,6 +1309,14 @@
 ]
 
 [[package]]
+name = "thread_local"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "threadpool"
 version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1356,6 +1393,11 @@
 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 = "unicase"
 version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1418,6 +1460,11 @@
 ]
 
 [[package]]
+name = "utf8-ranges"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "utf8parse"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1559,6 +1606,7 @@
 
 [metadata]
 "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
+"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14"
@@ -1673,6 +1721,8 @@
 "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
 "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
+"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467"
+"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e"
 "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
 "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841"
 "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
@@ -1702,6 +1752,7 @@
 "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
+"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
 "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
 "checksum timebomb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f0886f4b637067027d8c9a038a9249d95648689d1a91009d9abb895625f883a"
@@ -1711,6 +1762,7 @@
 "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
 "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
 "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 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"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@@ -1720,6 +1772,7 @@
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6"
+"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
 "checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
diff --git a/rustc_deps/Cargo.toml b/rustc_deps/Cargo.toml
index 54465a2..1336087 100644
--- a/rustc_deps/Cargo.toml
+++ b/rustc_deps/Cargo.toml
@@ -39,6 +39,7 @@
 pin-utils = "=0.1.0-alpha.3"
 pretty_assertions = "0.5.1"
 rand = "0.5"
+regex = "1.0.6"
 rouille = "2.1.0"
 rust-crypto = "0.2"
 rustc-serialize = "0.3"
diff --git a/rustc_deps/vendor/aho-corasick/.cargo-checksum.json b/rustc_deps/vendor/aho-corasick/.cargo-checksum.json
new file mode 100644
index 0000000..1a37b83
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".cargo_vcs_info.json":"b869cb0cca6ec13606e3ece69608480b18434cdfce871029d792c596d72fbbc4","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"2b5e42ae354311f29e53b600dffb398db134de1747c4ac96fd16fc16fbb9d4d1","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"9fb3256ce6fc5b25c9a92fe3b8f7a82a26d380fcf6121c934c2bb6f85102fede","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"c74b297ed2217e4784614573a8b44c61dfe5173985c43616e43a3f608973ff2e","benches/random.txt":"9386fb3efedc7ffbd09fb49088347f1056bc2d90a861009fa2f804cdb714efcb","examples/dict-search.rs":"0dac88736039262dfb8df9ff85ece18de90dd4da9b8b895cf4d57bf33167b224","src/autiter.rs":"b3bd067bf6c25708109870afbb5d09e9a04d0f2f596f59c368e42ddbc7c65f93","src/full.rs":"acb6389d210e7bc4125f0ebb6f268b712e60ec50b58b9c4094a8083bb8f4caf2","src/lib.rs":"fdddbb688fbc71461242b94e1cfb3dfbf0a9f06b2c70a6e83de15a0e54804a28","src/main.rs":"fc867cb5f0b02d0f49ecab06b72c05a247cbcf3bf9228c235de8e787bda7bef5"},"package":"1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"}
\ No newline at end of file
diff --git a/rustc_deps/vendor/aho-corasick/.cargo_vcs_info.json b/rustc_deps/vendor/aho-corasick/.cargo_vcs_info.json
new file mode 100644
index 0000000..bc741be
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "6e17854c0f63acd101e0d985e6d2441ee24e9eff"
+  }
+}
diff --git a/rustc_deps/vendor/aho-corasick/COPYING b/rustc_deps/vendor/aho-corasick/COPYING
new file mode 100644
index 0000000..bb9c20a
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/COPYING
@@ -0,0 +1,3 @@
+This project is dual-licensed under the Unlicense and MIT licenses.
+
+You may use this code under the terms of either license.
diff --git a/rustc_deps/vendor/aho-corasick/Cargo.toml b/rustc_deps/vendor/aho-corasick/Cargo.toml
new file mode 100644
index 0000000..155d48e
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/Cargo.toml
@@ -0,0 +1,72 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "aho-corasick"
+version = "0.6.9"
+authors = ["Andrew Gallant <jamslam@gmail.com>"]
+exclude = ["/benches/sherlock.txt", "/ci/*", "/.travis.yml", "/Makefile", "/ctags.rust", "/session.vim"]
+description = "Fast multiple substring searching with finite state machines."
+homepage = "https://github.com/BurntSushi/aho-corasick"
+readme = "README.md"
+keywords = ["string", "search", "text", "aho", "corasick"]
+license = "Unlicense/MIT"
+repository = "https://github.com/BurntSushi/aho-corasick"
+[profile.test]
+debug = true
+
+[profile.bench]
+debug = true
+
+[profile.release]
+debug = true
+
+[lib]
+name = "aho_corasick"
+
+[[bin]]
+name = "aho-corasick-dot"
+path = "src/main.rs"
+test = false
+bench = false
+doc = false
+
+[[bench]]
+name = "bench"
+path = "benches/bench.rs"
+test = false
+bench = true
+[dependencies.memchr]
+version = "2"
+[dev-dependencies.csv]
+version = "1"
+
+[dev-dependencies.docopt]
+version = "1"
+
+[dev-dependencies.memmap]
+version = "0.6"
+
+[dev-dependencies.quickcheck]
+version = "0.7"
+default-features = false
+
+[dev-dependencies.rand]
+version = "0.5"
+
+[dev-dependencies.serde]
+version = "1"
+
+[dev-dependencies.serde_derive]
+version = "1"
+[badges.travis-ci]
+repository = "BurntSushi/aho-corasick"
diff --git a/rustc_deps/vendor/aho-corasick/LICENSE-MIT b/rustc_deps/vendor/aho-corasick/LICENSE-MIT
new file mode 100644
index 0000000..3b0a5dc
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/LICENSE-MIT
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew Gallant
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/rustc_deps/vendor/aho-corasick/README.md b/rustc_deps/vendor/aho-corasick/README.md
new file mode 100644
index 0000000..25e9ef9
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/README.md
@@ -0,0 +1,55 @@
+This crate provides an implementation of the
+[Aho-Corasick](http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm)
+algorithm. Its intended use case is for fast substring matching, particularly
+when matching multiple substrings in a search text. This is achieved by
+compiling the substrings into a finite state machine.
+
+This implementation provides optimal algorithmic time complexity. Construction
+of the finite state machine is `O(p)` where `p` is the length of the substrings
+concatenated. Matching against search text is `O(n + p + m)`, where `n` is
+the length of the search text and `m` is the number of matches.
+
+[![Build status](https://api.travis-ci.org/BurntSushi/aho-corasick.png)](https://travis-ci.org/BurntSushi/aho-corasick)
+[![](http://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick)
+
+Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
+
+
+### Documentation
+
+[https://docs.rs/aho-corasick/](https://docs.rs/aho-corasick/).
+
+
+### Example
+
+The documentation contains several examples, and there is a more complete
+example as a full program in `examples/dict-search.rs`.
+
+Here is a quick example showing simple substring matching:
+
+```rust
+use aho_corasick::{Automaton, AcAutomaton, Match};
+
+let aut = AcAutomaton::new(vec!["apple", "maple"]);
+let mut it = aut.find("I like maple apples.");
+assert_eq!(it.next(), Some(Match {
+    pati: 1,
+    start: 7,
+    end: 12,
+}));
+assert_eq!(it.next(), Some(Match {
+    pati: 0,
+    start: 13,
+    end: 18,
+}));
+assert_eq!(it.next(), None);
+```
+
+
+### Alternatives
+
+Aho-Corasick is useful for matching multiple substrings against many long
+strings. If your long string is fixed, then you might consider building a
+[suffix array](https://github.com/BurntSushi/suffix)
+of the search text (which takes `O(n)` time). Matches can then be found in
+`O(plogn)` time.
diff --git a/rustc_deps/vendor/aho-corasick/UNLICENSE b/rustc_deps/vendor/aho-corasick/UNLICENSE
new file mode 100644
index 0000000..68a49da
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/rustc_deps/vendor/aho-corasick/benches/bench.rs b/rustc_deps/vendor/aho-corasick/benches/bench.rs
new file mode 100644
index 0000000..0e68e2a
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/benches/bench.rs
@@ -0,0 +1,373 @@
+#![feature(test)]
+
+extern crate aho_corasick;
+extern crate test;
+
+use std::iter;
+
+use aho_corasick::{Automaton, AcAutomaton, Transitions};
+use test::Bencher;
+
+const HAYSTACK_RANDOM: &'static str = include_str!("random.txt");
+const HAYSTACK_SHERLOCK: &'static str = include_str!("sherlock.txt");
+
+fn bench_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
+    b: &mut Bencher,
+    aut: AcAutomaton<P, T>,
+    haystack: &str,
+) {
+    b.bytes = haystack.len() as u64;
+    b.iter(|| assert!(aut.find(haystack).next().is_none()));
+}
+
+fn bench_box_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
+    b: &mut Bencher,
+    aut: AcAutomaton<P, T>,
+    haystack: &str,
+) {
+    b.bytes = haystack.len() as u64;
+    let aut: &Automaton<P> = &aut;
+    b.iter(|| assert!(Automaton::find(&aut, haystack).next().is_none()));
+}
+
+fn bench_full_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
+    b: &mut Bencher,
+    aut: AcAutomaton<P, T>,
+    haystack: &str,
+) {
+    let aut = aut.into_full();
+    b.bytes = haystack.len() as u64;
+    b.iter(|| assert!(aut.find(haystack).next().is_none()));
+}
+
+fn bench_full_aut_overlapping_no_match<P: AsRef<[u8]>, T: Transitions>(
+    b: &mut Bencher,
+    aut: AcAutomaton<P, T>,
+    haystack: &str,
+) {
+    let aut = aut.into_full();
+    b.bytes = haystack.len() as u64;
+    b.iter(|| assert!(aut.find_overlapping(haystack).count() == 0));
+}
+
+fn bench_naive_no_match<S>(b: &mut Bencher, needles: Vec<S>, haystack: &str)
+        where S: Into<String> {
+    b.bytes = haystack.len() as u64;
+    let needles: Vec<String> = needles.into_iter().map(Into::into).collect();
+    b.iter(|| assert!(!naive_find(&needles, haystack)));
+}
+
+#[bench]
+fn bench_construction(b: &mut Bencher) {
+    b.iter(|| {
+        AcAutomaton::new(test::black_box(
+            [
+                "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK", "HOL",
+                "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh", "JoH", "Joh", "SHE",
+                "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "aDL", "aDl", "adL", "adl", "bAK",
+                "bAk", "bAK", "baK", "bak", "baK", "hOL", "hOl", "hoL", "hol", "iRE", "iRe",
+                "irE", "ire", "jOH", "jOh", "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt",
+                "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe",
+            ].iter()
+                .map(|x| *x),
+        ))
+    })
+}
+
+#[bench]
+fn bench_full_construction(b: &mut Bencher) {
+    b.iter(|| {
+        AcAutomaton::new(test::black_box(
+            [
+                "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK", "HOL",
+                "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh", "JoH", "Joh", "SHE",
+                "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "aDL", "aDl", "adL", "adl", "bAK",
+                "bAk", "bAK", "baK", "bak", "baK", "hOL", "hOl", "hoL", "hol", "iRE", "iRe",
+                "irE", "ire", "jOH", "jOh", "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt",
+                "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe",
+            ].iter()
+                .map(|x| *x),
+        )).into_full()
+    })
+}
+
+fn haystack_same(letter: char) -> String {
+    iter::repeat(letter).take(10000).collect()
+}
+
+macro_rules! aut_benches {
+    ($prefix:ident, $aut:expr, $bench:expr) => {
+        mod $prefix {
+#![allow(unused_imports)]
+use aho_corasick::{Automaton, AcAutomaton, Sparse};
+use test::Bencher;
+
+use super::{
+    HAYSTACK_RANDOM, haystack_same,
+    bench_aut_no_match, bench_box_aut_no_match,
+    bench_full_aut_no_match, bench_full_aut_overlapping_no_match,
+};
+
+#[bench]
+fn ac_one_byte(b: &mut Bencher) {
+    let aut = $aut(vec!["a"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_one_prefix_byte_no_match(b: &mut Bencher) {
+    let aut = $aut(vec!["zbc"]);
+    $bench(b, aut, &haystack_same('y'));
+}
+
+#[bench]
+fn ac_one_prefix_byte_every_match(b: &mut Bencher) {
+    // We lose the benefit of `memchr` because the first byte matches
+    // in every position in the haystack.
+    let aut = $aut(vec!["zbc"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_one_prefix_byte_random(b: &mut Bencher) {
+    let aut = $aut(vec!["zbc\x00"]);
+    $bench(b, aut, HAYSTACK_RANDOM);
+}
+
+#[bench]
+fn ac_two_bytes(b: &mut Bencher) {
+    let aut = $aut(vec!["a", "b"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_two_diff_prefix(b: &mut Bencher) {
+    let aut = $aut(vec!["abcdef", "bmnopq"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_two_one_prefix_byte_every_match(b: &mut Bencher) {
+    let aut = $aut(vec!["zbcdef", "zmnopq"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_two_one_prefix_byte_no_match(b: &mut Bencher) {
+    let aut = $aut(vec!["zbcdef", "zmnopq"]);
+    $bench(b, aut, &haystack_same('y'));
+}
+
+#[bench]
+fn ac_two_one_prefix_byte_random(b: &mut Bencher) {
+    let aut = $aut(vec!["zbcdef\x00", "zmnopq\x00"]);
+    $bench(b, aut, HAYSTACK_RANDOM);
+}
+
+#[bench]
+fn ac_ten_bytes(b: &mut Bencher) {
+    let aut = $aut(vec!["a", "b", "c", "d", "e",
+                        "f", "g", "h", "i", "j"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_ten_diff_prefix(b: &mut Bencher) {
+    let aut = $aut(vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
+                        "ebcdef", "fbcdef", "gbcdef", "hbcdef",
+                        "ibcdef", "jbcdef"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_ten_one_prefix_byte_every_match(b: &mut Bencher) {
+    let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
+                        "zecdef", "zfcdef", "zgcdef", "zhcdef",
+                        "zicdef", "zjcdef"]);
+    $bench(b, aut, &haystack_same('z'));
+}
+
+#[bench]
+fn ac_ten_one_prefix_byte_no_match(b: &mut Bencher) {
+    let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
+                        "zecdef", "zfcdef", "zgcdef", "zhcdef",
+                        "zicdef", "zjcdef"]);
+    $bench(b, aut, &haystack_same('y'));
+}
+
+#[bench]
+fn ac_ten_one_prefix_byte_random(b: &mut Bencher) {
+    let aut = $aut(vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
+                        "zdcdef\x00", "zecdef\x00", "zfcdef\x00",
+                        "zgcdef\x00", "zhcdef\x00", "zicdef\x00",
+                        "zjcdef\x00"]);
+    $bench(b, aut, HAYSTACK_RANDOM);
+}
+        }
+    }
+}
+
+aut_benches!(dense, AcAutomaton::new, bench_aut_no_match);
+aut_benches!(dense_boxed, AcAutomaton::new, bench_box_aut_no_match);
+aut_benches!(sparse, AcAutomaton::<&str, Sparse>::with_transitions,
+             bench_aut_no_match);
+aut_benches!(full, AcAutomaton::new, bench_full_aut_no_match);
+aut_benches!(full_overlap, AcAutomaton::new, bench_full_aut_overlapping_no_match);
+
+// A naive multi-pattern search.
+// We use this to benchmark *throughput*, so it should never match anything.
+fn naive_find(needles: &[String], haystack: &str) -> bool {
+    for hi in 0..haystack.len() {
+        let rest = &haystack.as_bytes()[hi..];
+        for needle in needles {
+            let needle = needle.as_bytes();
+            if needle.len() > rest.len() {
+                continue;
+            }
+            if needle == &rest[..needle.len()] {
+                // should never happen in throughput benchmarks.
+                return true;
+            }
+        }
+    }
+    false
+}
+
+#[bench]
+fn naive_one_byte(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["a"], &haystack_same('z'));
+}
+
+#[bench]
+fn naive_one_prefix_byte_no_match(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["zbc"], &haystack_same('y'));
+}
+
+#[bench]
+fn naive_one_prefix_byte_every_match(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["zbc"], &haystack_same('z'));
+}
+
+#[bench]
+fn naive_one_prefix_byte_random(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["zbc\x00"], HAYSTACK_RANDOM);
+}
+
+#[bench]
+fn naive_two_bytes(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["a", "b"], &haystack_same('z'));
+}
+
+#[bench]
+fn naive_two_diff_prefix(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["abcdef", "bmnopq"], &haystack_same('z'));
+}
+
+#[bench]
+fn naive_two_one_prefix_byte_every_match(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('z'));
+}
+
+#[bench]
+fn naive_two_one_prefix_byte_no_match(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('y'));
+}
+
+#[bench]
+fn naive_two_one_prefix_byte_random(b: &mut Bencher) {
+    bench_naive_no_match(b, vec!["zbcdef\x00", "zmnopq\x00"], HAYSTACK_RANDOM);
+}
+
+#[bench]
+fn naive_ten_bytes(b: &mut Bencher) {
+    let needles = vec!["a", "b", "c", "d", "e",
+                       "f", "g", "h", "i", "j"];
+    bench_naive_no_match(b, needles, &haystack_same('z'));
+}
+
+#[bench]
+fn naive_ten_diff_prefix(b: &mut Bencher) {
+    let needles = vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
+                       "ebcdef", "fbcdef", "gbcdef", "hbcdef",
+                       "ibcdef", "jbcdef"];
+    bench_naive_no_match(b, needles, &haystack_same('z'));
+}
+
+#[bench]
+fn naive_ten_one_prefix_byte_every_match(b: &mut Bencher) {
+    let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
+                       "zecdef", "zfcdef", "zgcdef", "zhcdef",
+                       "zicdef", "zjcdef"];
+    bench_naive_no_match(b, needles, &haystack_same('z'));
+}
+
+#[bench]
+fn naive_ten_one_prefix_byte_no_match(b: &mut Bencher) {
+    let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
+                       "zecdef", "zfcdef", "zgcdef", "zhcdef",
+                       "zicdef", "zjcdef"];
+    bench_naive_no_match(b, needles, &haystack_same('y'));
+}
+
+#[bench]
+fn naive_ten_one_prefix_byte_random(b: &mut Bencher) {
+    let needles = vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
+                       "zdcdef\x00", "zecdef\x00", "zfcdef\x00",
+                       "zgcdef\x00", "zhcdef\x00", "zicdef\x00",
+                       "zjcdef\x00"];
+    bench_naive_no_match(b, needles, HAYSTACK_RANDOM);
+}
+
+
+// The organization above is just awful. Let's start over...
+
+mod sherlock {
+    use aho_corasick::{Automaton, AcAutomaton};
+    use test::Bencher;
+    use super::HAYSTACK_SHERLOCK;
+
+    macro_rules! sherlock {
+        ($name:ident, $count:expr, $pats:expr) => {
+            #[bench]
+            fn $name(b: &mut Bencher) {
+                let haystack = HAYSTACK_SHERLOCK;
+                let aut = AcAutomaton::new($pats).into_full();
+                b.bytes = haystack.len() as u64;
+                b.iter(|| assert_eq!($count, aut.find(haystack).count()));
+            }
+        }
+    }
+
+    sherlock!(name_alt1, 158, vec!["Sherlock", "Street"]);
+
+    sherlock!(name_alt2, 558, vec!["Sherlock", "Holmes"]);
+
+    sherlock!(name_alt3, 740, vec![
+        "Sherlock", "Holmes", "Watson", "Irene", "Adler", "John", "Baker",
+    ]);
+
+    sherlock!(name_alt3_nocase, 1764, vec![
+        "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK",
+        "HOL", "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh",
+        "JoH", "Joh", "SHE", "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat",
+        "aDL", "aDl", "adL", "adl", "bAK", "bAk", "bAK", "baK", "bak", "baK",
+        "hOL", "hOl", "hoL", "hol", "iRE", "iRe", "irE", "ire", "jOH", "jOh",
+        "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt", "waT", "wat",
+        "ſHE", "ſHe", "ſhE", "ſhe",
+    ]);
+
+    sherlock!(name_alt4, 582, vec!["Sher", "Hol"]);
+
+    sherlock!(name_alt4_nocase, 1307, vec![
+        "HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "hOL", "hOl",
+        "hoL", "hol", "sHE", "sHe", "shE", "she", "ſHE", "ſHe", "ſhE", "ſhe",
+    ]);
+
+    sherlock!(name_alt5, 639, vec!["Sherlock", "Holmes", "Watson"]);
+
+    sherlock!(name_alt5_nocase, 1442, vec![
+        "HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "WAT", "WAt",
+        "WaT", "Wat", "hOL", "hOl", "hoL", "hol", "sHE", "sHe", "shE", "she",
+        "wAT", "wAt", "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe",
+    ]);
+}
diff --git a/rustc_deps/vendor/aho-corasick/benches/random.txt b/rustc_deps/vendor/aho-corasick/benches/random.txt
new file mode 100644
index 0000000..dfae5cd
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/benches/random.txt
@@ -0,0 +1,513 @@
+
+mnxnsynfvuugtbxsxbfxwreuspglnplefzwsp
+tacfqcwnmodnmgnyiuvqoco
+z
+
+qjuozfkexn
+zoaxzncje
+sldhqtmgxzyurfyzwazmmu
+bbeuv
+mzsrihycwcb
+xzfqozfmlnpmrzpxxxytqs
+xrg
+mcplby
+nmslhfgjowhzfxsvyddydnsyehdskbydbjksqtpet
+indvfw
+bvjvvw
+
+pddufodyqtyixbndtumndyz
+xjjhtuvmsxhuwqulqtjhqrdqrmtbcphvyuqllocrnkpfv
+zemshhz
+wss
+xewlrxfmgxnwgphcgefa
+mbgsgbzrtthxweimcqzcaaheurdmd
+osqefupespvh
+z
+tvvlakwzwjbrgjzfgubsmmonav
+pjdskxcfgapsm
+zqktqgkrcdrlskx
+zwwfebhguskho
+zlvvw
+czwm
+gojnpmboehlsazbexjjnuscqftrfufngygjdxcydib
+d
+afigycivicnknfxl
+ljuwuopctiftfwctxecwipjnljyef
+jonwbkodomzhqvlf
+jdkizhognqsdogunwedjsmsdzho
+zxvni
+oynfjf
+muvokjuqz
+azuwrwtuxzfopwrcex
+ixrjinlvxjmn
+blaegnmbhsgsbmebwazaeguugtkowexgnqtbfkldadddv
+tzabyoftyov
+ctbtqbzscxzviuvcigwuwusrdro
+ljynr
+gnnnyyxslrhsbj
+hhzlw
+hijalf
+rxlfqk
+mhaofforwznvmcgplinludpgkucpa
+gvvxsqqfmu
+xxqhoyosixjfhjuxpv
+faadjpvamjekreepizurntvwdynozfawsfawyms
+
+lcbutr
+aqyxvpozkjrecrkl
+lfmochahrr
+ptqyomjlwo
+vcmslulznx
+lmlsskcihrmxauztuarydlp
+beiqsrfnmvmlmybmwpektjbikvpggthpabqsgmjhnthvysuhwbigillugjsp
+dfsuegseffwcsnvsrqedytblbpzbfeyfsq
+kypvqctrkuds
+ylqeduokzgdqaxelhftxnxbidu
+bprzyayfopxdsmfhhfqowa
+ymiutdtlfaaxpbtaeslv
+ggago
+
+owpbicekdeykzfgcbgzobdvvrtetvcv
+xsrlgingstiez
+gyncqvq
+xasohmeiwyscpehctmzmsnjklg
+xsudghakxlw
+dzqlfptjogzpkvwuticcyugnyopypuqqc
+wlxshxbhdvuherumoppcc
+
+znyaptivzncvkpeyeipynqefjxjjcsgfqbnezeebtowdrbjaqjlbxwvyikrmxjwoxngqgvfpbniftnmszuxg
+umwpwwyvufy
+pallkjtnrmtauqxauewgygwkjjwebbkabhtxticxmxfujpxlrpzlrozfslkzfdsswlmmsbdgjwmjnummk
+dhsxylejzityahtqqzmohrpzjprrsraztpnuagtyzfjdekthvdogfidksrdppr
+ybc
+fyukknoqfnkllkwflwempjijxgo
+dltvlau
+rhvrvlwsribfctuzodfqkdczfzxnetqqzflnhiyl
+goxmcasmq
+wljbhwkpahdotqhhrbhqzijv
+lszewkgdmkezvgmbmllhpksdkoiwgkvqjmurshrptlctqsosuurndcuzjfwherotv
+dudxxihygxblhgchbgzyzffb
+eht
+fvwxvqoltdcsd
+rkuig
+e
+axhsacsmnicugul
+rubtdlhjqndxdzzwfnkuzy
+swxteuyxxsktkjgv
+hzwwodlqaq
+vxgecev
+qnwla
+vdxjuzpyoqhpmuunyffptopmeauhycs
+dkzo
+awrfzatzohslgvqlaezepmli
+qgxatixvpkkhvkumbwmwcagtgyfljdok
+amdnzstpvcqj
+xsrvwvhjirzfgkessve
+qezwbfltfbikbmoasvoflozsjhrljnszqiciuqmflrlqowwkoevuumh
+babskcvavmtvsxqsewirucwzajjcfcqwsydydqo
+ywfurpsl
+edacsjjkjjewkxfoh
+dcgkfpcjezurnuhiatrczcp
+xsatnimwbcciu
+grzmbrsvvcyigcbmcqfwiiknrohveubhyijxeyzfm
+kqyewccgcqrrrznwxmoztlyseagbpyho
+najju
+nis
+awgzdvfjkzlrsjcqfeacx
+oisuflfigrjaex
+desbdulyuwqxuxianyypybxwlql
+ekmqgspvqpftpwswayh
+egbyj
+fznzprhvnnwcxgcc
+wfdsueieosmugirxbymbpmfrspvrktjzguxm
+qkjrufshwnfwwpbhukdjlaqvljlgubmqmhnha
+hwqpudgnblhlxppbrmbznotteivuzguuwlhtkytky
+w
+yofkyzbpg
+cenolnfnllkvhikrpttcxgqxmufvorekjruyjxmr
+
+hyexmpjijgzumawp
+cdbevdilgopbzlo
+fivelagckslkugdxprjxkylizewcptwxfhomzuituujixchadmnjoktnqa
+csojvlinzmmkkfzqueamnuwkanzdzsavgohposbuoamoevehqrmcxdsuyelvvctoejzoertqormhaaxwofvjzekwt
+sbkghhnhutrvwtyjaxndzyjamrhx
+jjyqy
+majwbnrhveuhrsbbbjrwpwuplifeseylqh
+wyvutpxnkrnkuxxetjkkifpqb
+dyzucmbcvgnjeecm
+hz
+uhnuipthxrzkqluosvk
+lwqqzsdwiwvwaqfwlvubadlyizlo
+jbd
+oyzjeu
+kydjkbsqxnbfiuesc
+smeubjqrcxdvhsabzceyglqjzbfmoacmwvwjbhhxbr
+uabipgecujfdfxpmdzrscdyvefizabgspqjrrkmgjt
+xgvdgzryz
+lw
+uimob
+ifhn
+bqph
+ole
+g
+wt
+k
+yslzrkwkundxfdibwqvucemepqxlmlpyngabbeciuzhptpjdetyngrtxrdtzmvq
+ccwapidp
+
+bwvrgvmtshevrophy
+ni
+fdkplu
+mdykey
+i
+rhsrenoetdggpjb
+djmkplpeabsholx
+judxtub
+fooakqwvocvpcrvxqhvtmpvhkrecy
+uuxscjillynilbkrgt
+evtinrmilniguarqritpeipwochmdw
+sxaqzjybydyvnmmjtdcgkjnqfcklbfpkdfyewgcukqoiegyfp
+kg
+ovrwieqhy
+jcxqtkerzjwhs
+xeonglszbgypafhmqcaseimzjgebkvigbqwsayrnrprtuvhsxyitfqygohgorcdnufbcyvevvgzmjrgjqqquwkszplogx
+zdketqqv
+yebckucwayckeezfvtnavglpjh
+zorkfrwk
+pad
+xqaquxudybwtgixbfktinctfirjfdayh
+rieknj
+ebk
+qzbcfywfdmhsdruhopovemafijbscagllkmhmof
+
+asbsnbddlobwoqatfhkbhhsymzqxjuixwreheugvngmgcuqpkjhhfwpbarqaxrwgwnjbanljlds
+etevdvlc
+lqyjrnmenhn
+k
+tsf
+zczgeavcexh
+jlpuxywtsrvnvluruqhecjca
+ir
+rikrgkmhwaosodkxgcnrexfmdrszhnmutpvwztg
+bffjqovvkemctnsgeh
+weysbhzixiipfithjfsk
+usyzvaiyuhmksfluoirfbnsu
+o
+cgawpdakaszeafdtbdkqtlzkrpnoqomqvuaqcfmzgvfegovtfaonelpv
+izmrcjlk
+xmzemniyrzy
+knqexaafsdlimdamcrprlshq
+qkmqw
+dntgjwsibclvposdwjuklvtejjjdjibgpyynqpgprvvaetshhmvfkcpb
+otvazkrkklrxfotpopyjte
+fghkcnpi
+rulyaihsowvcgbzeiblhuhhfbmncqsuuqcxvseorn
+exirzfmojnxcoqom
+zsgpgtokun
+zvamxfocorganbtlafifwdqmqtsnktbwwtewborq
+
+cxlnaspjqvsitjyzyriqsuorjsrvzqenisprttudxntsbqrpjtdkxnwcwgjyxmgtqljcrmrbrmyvosojzlumcmjcgfjsdehec
+mvx
+mt
+mckr
+teulvroifk
+laaicc
+koufy
+bexmwsvyarnznebdfy
+ripvviosbqijsxnjilwddaqaqemzsdarnxmfooxghoypizwtbueo
+ljycycuqwfnzbambibqdixmkkvwtubepla
+cis
+kcg
+vmbbiuuoamenzepuagpfujevfstqtndjxjchdvycfrrrowochtjdmkklgnhf
+pmorrwguxkvdxpluatagaziin
+
+uwvzbmkmykjkmknzppklx
+pnzxuvsrjunqxercsnvayhykcazdeclomdsasgkpqpiufyfqsxhj
+yceizkddwojgweegcllaagpvrpo
+ek
+kuxxgbezqyxvfaxdwnqdgqsmneijunxzlwxkrs
+ldldbrxmvtjlqxifngmactzqcygkvuteffcmvphevilabgukatqakamjlridznodcvblvlogulmcixxfimh
+iuzjootuywjqklolzzhpeaynydjwtufjavbozxnzckuzdodkvkjfmhinelv
+swlfkcufscfcovmghqwcrtxjukwafoeogrkgubbqgwzm
+gjcylkwgzroubdssuqeykqjcmguso
+fzq
+srfvysoxtlylctp
+
+pbfeiuzwoyixews
+ocvvunfsjnrtklmuuzjojw
+xdjcnrpqhmpmpcwacpcdtmbsczvhllkqapzjuaf
+nfnuvjz
+fwnuiyqpn
+wshxxxpzzxp
+hibrxcfeqca
+
+wqhlllarl
+bukcbojv
+plrytapy
+xm
+vlgfqoyzdczqbbaxjwbjjevjhxgopuqvqcrj
+vpjqfbdnsdxlbuuiqocvrhap
+mgumjbvnnzgnrdru
+gcgzugazxdcamrhczfzhtmdjj
+uislwq
+vooai
+zjuqfmebuzsqngzekyajujkopvayxtdzvugwwucvlsbrnhitfotmhhmgddlzlvqrkcponictrfweuilfjiuoabkfdvpjiqjrrgi
+aptjfhmrnxaq
+hbs
+w
+mwmoxqvucwygunplzvxtxpk
+fgmqmtlorfzytjdzffsosfccnfwugrsrynuej
+rpmpenrhsxoefnblyumjqwvuyszyppnttuyvazjdug
+zdzxraxkroknkmqgvuoqeqdtvclsvvuwmdwzfugcpteohlogxubyoebvrzbqzklvehfcqadtdrkpubfhmokzwyosogepwragcpwxo
+ax
+dz
+de
+
+thvkdmnbdws
+
+ejmubw
+umvwkaubzurf
+wyxtxeluaoox
+wwbioobtgmkebxo
+miglgnafmdarzkeblyjctuayzyoeqnfnbtrcbymdzkzg
+loavxq
+kzhllgsenxlbgdbfzwbg
+yxflogzsohlcycbyzegeubfflouvtuatixhjvicjegltjiy
+jigqfjppafdiarc
+mcnmwtachgearonfcymvjbrnljjxmlzkudvzqsarnfysmxlfrtlvjxwvpdbhvwysnvcdozfcruhjwnucdzakkilmlfgjiolcatpfusm
+
+n
+pdjunfcz
+dc
+edxkkxabsbvmvifiinnoccki
+bc
+gwtwsvorwzfqpz
+exidmexstfflkhi
+s
+s
+c
+wtcjfywlayhpbqktcepoybowtkrmnumqsg
+ozclkgjdmdk
+jmegtbunyexurvfexhqptnqzie
+tkoenpagzwqfawlxvzaijsjqhmg
+swodqfjpdqcbkc
+ujokogocyaygdibgpglecis
+shlmdmgonvpuaxlhrymkxtiytmv
+brhk
+jmsyiuomiywxhegilycjprkyfgojdo
+
+wzdzrgpdiosdsvkcw
+odlnmsfnjrcsnflviwvawybpczdkzvdocpwrmavz
+p
+ubowamlskcqhdxuckrxa
+fawhntiwhmdwkddnahmtajqqazpdygttqivhdiodkcpcwv
+gmxujmmaufmbipaiulhurzkfdg
+eixjhmbaeoybiwk
+kumntgrgiofcmujlzbcopuobambsw
+mnjkqiyb
+iktwnsnv
+hfuzcl
+tqiyqvagbqgtowpjbedgjot
+dfemvamelxadkztogliizdtsddoboafawficudlefo
+raecmxiiibljryswntpfed
+mbwrtsebkeegw
+x
+epp
+he
+
+vnztrswhiusokqdkmsnpuswucvfhcthjbtam
+baxlwidsgbdpzvnlj
+tcbjjoadrzo
+aiidahyllzzsg
+
+igebuubweicbssgddpmqxunrawavuglmpxrtkqsvjjtscibqiejjfgfnovokodmqcqitlteiakooupvzkwucucrfdzjvjbqbkgutoybmpfvhbutigdxhfiqfplyciz
+cnrhbjdnjftwfwlwzrdkwhajgsizsi
+qfntnt
+okqyfnbresp
+asyg
+mjqdkdyggdxzwuzglays
+h
+ifaqcazoy
+fol
+vvsusbnugduxsceozmsarbp
+epjwtorx
+bwiuxxiyc
+cw
+bwogruhctwkfvbexjnwircykxyzjmats
+kygiochfwlpsvmxcgmtjrgvfdptd
+q
+qmpqe
+
+z
+jghffhqfoecmszunhxmzmzhlmbrvjabhrkihgjmvckhkfpaygjkg
+
+kfiyfgounmhlvhupswqdgws
+ezzdpyqucqoocsdcjtruqpokldfkmjhqzoynirybsifyaxnaxppthjoqy
+nwetlgzwrhkhtuubbkbepuhbllxspvagxrqokwnrhkbwdwtp
+hlazomrhqogoaxypqaszwfxxmutvbpuuvpdffuqskcbzlwyzcssnflkwiydoveyxjnzllzhyozbsa
+hwnitkwbxcyibbqsluuqywbk
+
+ozpfjsdrc
+yoepefuy
+lvmspzepnetra
+genbrcrmuqfvkaouvuymoxhcxotjjhk
+pcshyqgbmqdubsdajnyfqvxkqvywffzn
+ukhcbyzwslqeq
+otfrmcbnhbyffxqregqoufdxucjunwdhlqqeiiawbxlpqeyzzopfungrryqdykgizrhqodirvazm
+dhpfhzyq
+cloz
+eduupqifolfekve
+qiec
+ishnjukvomntmdthlkajxpiwk
+y
+axl
+tmyskjqkjsvumizlal
+wvvolwewsfxhhdieuagdcuhwsgqvswpbkdkpxskloalmr
+ryfmhe
+z
+mmbpgsyrfvzdatbjrjhuipwt
+llzwizmmuulgwocowwmugtaoewkhnqxparvtynlffffdfcocdbba
+
+pyczkzbmcgrdnxnmezsx
+gsqe
+mcocxcolcynhpecstsn
+opnpplkccobjuhtbhirpzfxuktmpsiwbvsgiaavvdge
+wpaldxzasnrbvtugjwytvtfttrh
+zxecurevkjiyxy
+wtnovebcmglkktic
+fdpwfgvlvovxrwh
+bmwgdullzy
+uzwhagxinwqifxjbcntqzqoxkmpqxhe
+jrfizsnwxwnnhb
+inapddlahrp
+
+ndtvkceobe
+buskgghihdjmjlwfc
+j
+rkvffxwtmzoeruhlsurwtnuh
+cbvkhfepkdishfpqvijzrpleuy
+jzdpxjhcgqnybssfegvrnpgyehdqpgjwudbwrjbavp
+xzzvgqdrdwajmdmj
+vfatwsxvwfdbdhnijdujoyotwvwjipuuetichcfmvgrsnjpqaaezjtkvc
+lbfoqgfshrtwgdqufwnfuitdrjydqctqixlzufkdbp
+zgau
+qefdpmtkecvtj
+kuphldkvnzdtpd
+dti
+fpd
+gfrliyegxsb
+i
+qsddsrmkyfgzrjeqnitmnypbcakh
+vfbvbrpuogzhzrbmklvhji
+nkz
+xlufbaoblbmeub
+alwuzxzmobwdukvwnkiwmuqhuxfhevogdnqtmxjptqznrk
+cngpoty
+
+ms
+qvenfg
+dmeaffm
+jycfgnanbmoamhmarkmjcagbp
+ysqmbhopgx
+jczbzgwedsp
+
+zxzwjrxcwdtleizjlvifjwgxiibezwxhtzywqdi
+mtgnlu
+xboxirdchurkfnklnpkapnqfxnhrxyseiujrznjm
+
+zm
+atddskbghcahlhql
+szshwzmmvu
+befdtpouamwhiisyybispkchpjhownatawjfbx
+
+ennkzbrlygd
+zbt
+upphzpdwzmlhhhbqvjsfmbnrar
+ddcs
+ipbxgzyudjyongtcyygncojdufnufqpdppgvq
+gc
+isu
+foa
+wf
+jdlvqxgfbowhohhyyngbcs
+zjuwjyucdwblatsnywaaoftlcamfbcnw
+lzrioesuhoeevczuwrnltmkahfwiu
+uicggfbddqltnjyxfltbnaekncnyxsit
+zkxsqkqrwrzrxgxbsgxatybfr
+
+ptvmfyxdcglbfipcguqthjygzqnpqssscukzawynidtchjrrxwuxifoe
+w
+ohu
+vg
+zagpowezvbniybgold
+lhqseqcxteiqtgnpanpvrmvvlltxh
+mtfnxn
+wyodtg
+
+rawpbgtpbaktqzmmpzxmrlwpvvmdsl
+widcfbirvswraukbmkhf
+vplrueuxomjkqrtjgyxjdkexttzyozawyq
+hrpbahllznvmjudzxpbbv
+tlavfrxygjfipkupwnbacltcfepeg
+icu
+otxcu
+aewazy
+hl
+
+fmrp
+qaacthwzohenzjr
+xbyebba
+rvkph
+mkhhmh
+swme
+zjmdoypaktglcyzobquunvthcdwegtbywpijxd
+jvkuhnxqc
+gibhqgjojsxt
+bodbktzomiqujtbstqiyquwvqgufphqstenxvddkvtdh
+bpusrxkfi
+zgp
+pmxvgamydyakituvvsucsuidrlznupcsinltmrahulhepxmhoqtfvpjkxzhrrinncuh
+jzgkjjhjqykzelaszvcwvvwbnzsxdeaerfnaravk
+ynanrqyrxo
+zsmuxofullob
+brklgrcqefdyoczy
+qkpls
+snhqumae
+iqdtzjadzzvnqvdvjfsaf
+nfqfdqiramueblxkaqxbbkxwywzgdbndjjiqk
+tc
+kp
+cpuckbjsxhtxmomfesgxdpz
+oseif
+ybhxbvyxrpkrexrhjzoaxxohrhsniewsrktjnaztn
+ggelspdzhzbchruhbjbjidgjwdlhdycetqaswh
+jkgivsngygkbqtlmoj
+dwpnanfvitxg
+ospxbwxp
+wgvmvrnjescemdoiralbkvemalifxnyhrbdgodml
+hjtsnkzknkplbzsiwmneefdkihnhsamjsrxggclyjqgpqltizi
+
+
+sykgbuypwwhweab
+nvdkkkskmtiwpoerkon
+sx
+sbyflwwiqylbskdlxesmylpaz
+dnwcjenaluwesyywfaezznwkdwpoesxpu
+kie
+dslccwfryol
+gfhomgfn
+zprjtfqvkotktzidmoyrivall
+bunvsqkysdelozemnjoeqfolruulpbipm
+ullyzfahpkhkja
+hwd
+kvyqtprpuulgsk
+zotbkcadnxmfvqmtlbxalhughceyfcibtzzj
+vvpjbgxygl
+hpic
+mhrqd
+dv
+thehuzdbaacoidjoljbysnqwrrxxplrdznmgiukkvjqbopb
+moszjt
+rmtbunktkywqirveeqfa
+kse
+wbfflnatgzobjrxghjgvcsyxoruenxhyomutbptswjajawqjpqafpdcstkiyjuilimecgejpqmyciolgcmdpcstzdozbmnza
diff --git a/rustc_deps/vendor/aho-corasick/examples/dict-search.rs b/rustc_deps/vendor/aho-corasick/examples/dict-search.rs
new file mode 100644
index 0000000..b620cc2
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/examples/dict-search.rs
@@ -0,0 +1,138 @@
+// This example demonstrates how to use the Aho-Corasick algorithm to rapidly
+// scan text for matches in a large dictionary of keywords. This example by
+// default reads your system's dictionary (~120,000 words).
+extern crate aho_corasick;
+extern crate csv;
+extern crate docopt;
+extern crate memmap;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+
+use std::error::Error;
+use std::fs::File;
+use std::io::{self, BufRead, Write};
+use std::process;
+
+use aho_corasick::{Automaton, AcAutomaton, Match};
+use docopt::Docopt;
+use memmap::Mmap;
+
+static USAGE: &'static str = "
+Usage: dict-search [options] <input>
+       dict-search --help
+
+Options:
+    -d <path>, --dict <path>   Path to dictionary of keywords to search.
+                               [default: /usr/share/dict/words]
+    -m <len>, --min-len <len>  The minimum length for a keyword in UTF-8
+                               encoded bytes. [default: 5]
+    --overlapping              Report overlapping matches.
+    -c, --count                Show only the numebr of matches.
+    --memory-usage             Show memory usage of automaton.
+    --full                     Use fully expanded transition matrix.
+                               Warning: may use lots of memory.
+    -h, --help                 Show this usage message.
+";
+
+#[derive(Clone, Debug, Deserialize)]
+struct Args {
+    arg_input: String,
+    flag_dict: String,
+    flag_min_len: usize,
+    flag_overlapping: bool,
+    flag_memory_usage: bool,
+    flag_full: bool,
+    flag_count: bool,
+}
+
+fn main() {
+    let args: Args = Docopt::new(USAGE)
+                            .and_then(|d| d.deserialize())
+                            .unwrap_or_else(|e| e.exit());
+    match run(&args) {
+        Ok(()) => {}
+        Err(err) => {
+            writeln!(&mut io::stderr(), "{}", err).unwrap();
+            process::exit(1);
+        }
+    }
+}
+
+fn run(args: &Args) -> Result<(), Box<Error>> {
+    let aut = try!(build_automaton(&args.flag_dict, args.flag_min_len));
+    if args.flag_memory_usage {
+        let (bytes, states) = if args.flag_full {
+            let aut = aut.into_full();
+            (aut.heap_bytes(), aut.num_states())
+        } else {
+            (aut.heap_bytes(), aut.num_states())
+        };
+        println!("{} bytes, {} states", bytes, states);
+        return Ok(());
+    }
+
+    let rdr = try!(File::open(&args.arg_input));
+    if args.flag_full {
+        let aut = aut.into_full();
+        if args.flag_overlapping {
+            if args.flag_count {
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find_overlapping(&*mmap).count());
+            } else {
+                try!(write_matches(&aut, aut.stream_find_overlapping(rdr)));
+            }
+        } else {
+            if args.flag_count {
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find(&*mmap).count());
+            } else {
+                try!(write_matches(&aut, aut.stream_find(rdr)));
+            }
+        }
+    } else {
+        if args.flag_overlapping {
+            if args.flag_count {
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find_overlapping(&*mmap).count());
+            } else {
+                try!(write_matches(&aut, aut.stream_find_overlapping(rdr)));
+            }
+        } else {
+            if args.flag_count {
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find(&*mmap).count());
+            } else {
+                try!(write_matches(&aut, aut.stream_find(rdr)));
+            }
+        }
+    }
+    Ok(())
+}
+
+fn write_matches<A, I>(aut: &A, it: I) -> Result<(), Box<Error>>
+        where A: Automaton<String>, I: Iterator<Item=io::Result<Match>> {
+    let mut wtr = csv::Writer::from_writer(io::stdout());
+    try!(wtr.serialize(("pattern", "start", "end")));
+    for m in it {
+        let m = try!(m);
+        try!(wtr.serialize((aut.pattern(m.pati), m.start, m.end)));
+    }
+    try!(wtr.flush());
+    Ok(())
+}
+
+fn build_automaton(
+    dict_path: &str,
+    min_len: usize,
+) -> Result<AcAutomaton<String>, Box<Error>> {
+    let buf = io::BufReader::new(try!(File::open(dict_path)));
+    let mut lines = Vec::with_capacity(1 << 10);
+    for line in buf.lines() {
+        let line = try!(line);
+        if line.len() >= min_len {
+            lines.push(line);
+        }
+    }
+    Ok(AcAutomaton::with_transitions(lines))
+}
diff --git a/rustc_deps/vendor/aho-corasick/src/autiter.rs b/rustc_deps/vendor/aho-corasick/src/autiter.rs
new file mode 100644
index 0000000..dfad28f
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/src/autiter.rs
@@ -0,0 +1,530 @@
+use std::io::{self, BufRead};
+use std::marker::PhantomData;
+
+use memchr::{memchr, memchr2, memchr3};
+
+use super::{ROOT_STATE, StateIdx};
+
+/// An abstraction over automatons and their corresponding iterators.
+/// The type parameter `P` is the type of the pattern that was used to
+/// construct this Automaton.
+pub trait Automaton<P> {
+    /// Return the next state given the current state and next character.
+    fn next_state(&self, si: StateIdx, b: u8) -> StateIdx;
+
+    /// Return true if and only if the given state and current pattern index
+    /// indicate a match.
+    fn has_match(&self, si: StateIdx, outi: usize) -> bool;
+
+    /// Build a match given the current state, pattern index and input index.
+    fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match;
+
+    /// Return the set of bytes that have transitions in the root state.
+    fn start_bytes(&self) -> &[u8];
+
+    /// Returns all of the patterns matched by this automaton.
+    ///
+    /// The order of the patterns is the order in which they were added.
+    fn patterns(&self) -> &[P];
+
+    /// Returns the pattern indexed at `i`.
+    ///
+    /// The index corresponds to the position at which the pattern was added
+    /// to the automaton, starting at `0`.
+    fn pattern(&self, i: usize) -> &P;
+
+    /// Return the number of patterns in the automaton.
+    #[inline]
+    fn len(&self) -> usize {
+        self.patterns().len()
+    }
+
+    /// Returns true if the automaton has no patterns.
+    #[inline]
+    fn is_empty(&self) -> bool {
+        self.patterns().is_empty()
+    }
+
+    /// Returns an iterator of non-overlapping matches in `s`.
+    fn find<'a, 's, Q: ?Sized + AsRef<[u8]>>(
+        &'a self,
+        s: &'s Q,
+    ) -> Matches<'a, 's, P, Self>
+    where Self: Sized {
+        Matches {
+            aut: self,
+            text: s.as_ref(),
+            texti: 0,
+            si: ROOT_STATE,
+            _m: PhantomData,
+        }
+    }
+
+    /// Returns an iterator of overlapping matches in `s`.
+    fn find_overlapping<'a, 's, Q: ?Sized + AsRef<[u8]>>(
+        &'a self,
+        s: &'s Q,
+    ) -> MatchesOverlapping<'a, 's, P, Self>
+    where Self: Sized {
+        MatchesOverlapping {
+            aut: self,
+            text: s.as_ref(),
+            texti: 0,
+            si: ROOT_STATE,
+            outi: 0,
+            _m: PhantomData,
+        }
+    }
+
+    /// Returns an iterator of non-overlapping matches in the given reader.
+    fn stream_find<'a, R: io::Read>(
+        &'a self,
+        rdr: R,
+    ) -> StreamMatches<'a, R, P, Self>
+    where Self: Sized {
+        StreamMatches {
+            aut: self,
+            buf: io::BufReader::new(rdr),
+            texti: 0,
+            si: ROOT_STATE,
+            _m: PhantomData,
+        }
+    }
+
+    /// Returns an iterator of overlapping matches in the given reader.
+    fn stream_find_overlapping<'a, R: io::Read>(
+        &'a self,
+        rdr: R,
+    ) -> StreamMatchesOverlapping<'a, R, P, Self>
+    where Self: Sized {
+        StreamMatchesOverlapping {
+            aut: self,
+            buf: io::BufReader::new(rdr),
+            texti: 0,
+            si: ROOT_STATE,
+            outi: 0,
+            _m: PhantomData,
+        }
+    }
+}
+
+impl<'a, P: AsRef<[u8]>, A: 'a + Automaton<P> + ?Sized>
+        Automaton<P> for &'a A {
+    fn next_state(&self, si: StateIdx, b: u8) -> StateIdx {
+        (**self).next_state(si, b)
+    }
+
+    fn has_match(&self, si: StateIdx, outi: usize) -> bool {
+        (**self).has_match(si, outi)
+    }
+
+    fn start_bytes(&self) -> &[u8] {
+        (**self).start_bytes()
+    }
+
+    fn patterns(&self) -> &[P] {
+        (**self).patterns()
+    }
+
+    fn pattern(&self, i: usize) -> &P {
+        (**self).pattern(i)
+    }
+
+    fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
+        (**self).get_match(si, outi, texti)
+    }
+}
+
+/// Records a match in the search text.
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Match {
+    /// The pattern index.
+    ///
+    /// This corresponds to the ordering in which the matched pattern was
+    /// added to the automaton, starting at `0`.
+    pub pati: usize,
+    /// The starting byte offset of the match in the search text.
+    pub start: usize,
+    /// The ending byte offset of the match in the search text.
+    ///
+    /// (This can be re-captiulated with `pati` and adding the pattern's
+    /// length to `start`, but it is convenient to have it here.)
+    pub end: usize,
+}
+
+/// An iterator of non-overlapping matches for in-memory text.
+///
+/// This iterator yields `Match` values.
+///
+/// `'a` is the lifetime of the automaton, `'s` is the lifetime of the
+/// search text, and `P` is the type of the Automaton's pattern.
+#[derive(Debug)]
+pub struct Matches<'a, 's, P, A: 'a + Automaton<P> + ?Sized> {
+    aut: &'a A,
+    text: &'s [u8],
+    texti: usize,
+    si: StateIdx,
+    _m: PhantomData<P>,
+}
+
+// When there's an initial lone start byte, it is usually worth it
+// to use `memchr` to skip along the input. The problem is that
+// the skipping function is called in the inner match loop, which
+// can be quite costly if the skipping condition is never met.
+// Therefore, we lift the case analysis outside of the inner loop at
+// the cost of repeating code.
+//
+// `step_to_match` is the version of the inner loop without skipping,
+// and `skip_to_match` is the version with skipping.
+#[inline(never)]
+fn step_to_match<P, A: Automaton<P> + ?Sized>(
+    aut: &A,
+    text: &[u8],
+    mut texti: usize,
+    mut si: StateIdx
+) -> Option<(usize, StateIdx)> {
+    while texti < text.len() {
+        si = aut.next_state(si, text[texti]);
+        if aut.has_match(si, 0) {
+            return Some((texti, si));
+        }
+        texti += 1;
+        if texti + 4 < text.len() {
+            si = aut.next_state(si, text[texti]);
+            if aut.has_match(si, 0) {
+                return Some((texti, si));
+            }
+            texti += 1;
+            si = aut.next_state(si, text[texti]);
+            if aut.has_match(si, 0) {
+                return Some((texti, si));
+            }
+            texti += 1;
+            si = aut.next_state(si, text[texti]);
+            if aut.has_match(si, 0) {
+                return Some((texti, si));
+            }
+            texti += 1;
+            si = aut.next_state(si, text[texti]);
+            if aut.has_match(si, 0) {
+                return Some((texti, si));
+            }
+            texti += 1;
+            si = aut.next_state(si, text[texti]);
+            if aut.has_match(si, 0) {
+                return Some((texti, si));
+            }
+            texti += 1;
+        }
+    }
+    None
+}
+
+fn skip_to_match<P, A: Automaton<P> + ?Sized, F: Fn(&A, &[u8], usize) -> usize>(
+    aut: &A,
+    text: &[u8],
+    mut texti: usize,
+    mut si: StateIdx,
+    skip: F,
+) -> Option<(usize, StateIdx)> {
+    if si == ROOT_STATE {
+        texti = skip(aut, text, texti);
+    }
+    while texti < text.len() {
+        si = aut.next_state(si, text[texti]);
+        if aut.has_match(si, 0) {
+            return Some((texti, si));
+        }
+        if si == ROOT_STATE {
+            texti = skip(aut, text, texti + 1);
+        } else {
+            texti += 1;
+            if texti + 4 < text.len() {
+                si = aut.next_state(si, text[texti]);
+                if aut.has_match(si, 0) {
+                    return Some((texti, si));
+                }
+                texti += 1;
+                si = aut.next_state(si, text[texti]);
+                if aut.has_match(si, 0) {
+                    return Some((texti, si));
+                }
+                texti += 1;
+                si = aut.next_state(si, text[texti]);
+                if aut.has_match(si, 0) {
+                    return Some((texti, si));
+                }
+                texti += 1;
+                si = aut.next_state(si, text[texti]);
+                if aut.has_match(si, 0) {
+                    return Some((texti, si));
+                }
+                texti += 1;
+                si = aut.next_state(si, text[texti]);
+                if aut.has_match(si, 0) {
+                    return Some((texti, si));
+                }
+                texti += 1;
+            }
+        }
+    }
+    None
+}
+
+#[inline]
+fn skip1<P, A: Automaton<P> + ?Sized>(
+    aut: &A,
+    text: &[u8],
+    at: usize,
+) -> usize {
+    debug_assert!(aut.start_bytes().len() == 1);
+    let b = aut.start_bytes()[0];
+    match memchr(b, &text[at..]) {
+        None => text.len(),
+        Some(i) => at + i,
+    }
+}
+
+#[inline]
+fn skip2<P, A: Automaton<P> + ?Sized>(
+    aut: &A,
+    text: &[u8],
+    at: usize,
+) -> usize {
+    debug_assert!(aut.start_bytes().len() == 2);
+    let (b1, b2) = (aut.start_bytes()[0], aut.start_bytes()[1]);
+    match memchr2(b1, b2, &text[at..]) {
+        None => text.len(),
+        Some(i) => at + i,
+    }
+}
+
+#[inline]
+fn skip3<P, A: Automaton<P> + ?Sized>(
+    aut: &A,
+    text: &[u8],
+    at: usize,
+) -> usize {
+    debug_assert!(aut.start_bytes().len() == 3);
+    let (b1, b2, b3) = (
+        aut.start_bytes()[0], aut.start_bytes()[1], aut.start_bytes()[2],
+    );
+    match memchr3(b1, b2, b3, &text[at..]) {
+        None => text.len(),
+        Some(i) => at + i,
+    }
+}
+
+impl<'a, 's, P, A: Automaton<P> + ?Sized> Iterator for Matches<'a, 's, P, A> {
+    type Item = Match;
+
+    fn next(&mut self) -> Option<Match> {
+        if self.aut.start_bytes().len() == 1 {
+            let skip = skip_to_match(
+                self.aut, self.text, self.texti, self.si, skip1);
+            if let Some((texti, si)) = skip {
+                self.texti = texti + 1;
+                self.si = ROOT_STATE;
+                return Some(self.aut.get_match(si, 0, texti));
+            }
+        } else if self.aut.start_bytes().len() == 2 {
+            let skip = skip_to_match(
+                self.aut, self.text, self.texti, self.si, skip2);
+            if let Some((texti, si)) = skip {
+                self.texti = texti + 1;
+                self.si = ROOT_STATE;
+                return Some(self.aut.get_match(si, 0, texti));
+            }
+        } else if self.aut.start_bytes().len() == 3 {
+            let skip = skip_to_match(
+                self.aut, self.text, self.texti, self.si, skip3);
+            if let Some((texti, si)) = skip {
+                self.texti = texti + 1;
+                self.si = ROOT_STATE;
+                return Some(self.aut.get_match(si, 0, texti));
+            }
+        } else {
+            let step = step_to_match(self.aut, self.text, self.texti, self.si);
+            if let Some((texti, si)) = step {
+                self.texti = texti + 1;
+                self.si = ROOT_STATE;
+                return Some(self.aut.get_match(si, 0, texti));
+            }
+        }
+        None
+    }
+}
+
+/// An iterator of non-overlapping matches for streaming text.
+///
+/// This iterator yields `io::Result<Match>` values.
+///
+/// `'a` is the lifetime of the automaton, `R` is the type of the underlying
+/// `io::Read`er, and P is the type of the Automaton's pattern.
+#[derive(Debug)]
+pub struct StreamMatches<'a, R, P, A: 'a + Automaton<P> + ?Sized> {
+    aut: &'a A,
+    buf: io::BufReader<R>,
+    texti: usize,
+    si: StateIdx,
+    _m: PhantomData<P>,
+}
+
+impl<'a, R: io::Read, P, A: Automaton<P>>
+        Iterator for StreamMatches<'a, R, P, A> {
+    type Item = io::Result<Match>;
+
+    fn next(&mut self) -> Option<io::Result<Match>> {
+        let mut m = None;
+        let mut consumed = 0;
+'LOOP:  loop {
+            self.buf.consume(consumed);
+            let bs = match self.buf.fill_buf() {
+                Err(err) => return Some(Err(err)),
+                Ok(bs) if bs.is_empty() => break,
+                Ok(bs) => bs,
+            };
+            consumed = bs.len(); // is shortened if we find a match
+            for (i, &b) in bs.iter().enumerate() {
+                self.si = self.aut.next_state(self.si, b);
+                if self.aut.has_match(self.si, 0) {
+                    m = Some(Ok(self.aut.get_match(self.si, 0, self.texti)));
+                    consumed = i + 1;
+                    self.texti += 1;
+                    self.si = ROOT_STATE;
+                    break 'LOOP;
+                }
+                self.texti += 1;
+            }
+        }
+        self.buf.consume(consumed);
+        m
+    }
+}
+
+/// An iterator of overlapping matches for in-memory text.
+///
+/// This iterator yields `Match` values.
+///
+/// `'a` is the lifetime of the automaton, `'s` is the lifetime of the
+/// search text, and `P` is the type of the Automaton's pattern.
+#[derive(Debug)]
+pub struct MatchesOverlapping<'a, 's, P, A: 'a + Automaton<P> + ?Sized> {
+    aut: &'a A,
+    text: &'s [u8],
+    texti: usize,
+    si: StateIdx,
+    outi: usize,
+    _m: PhantomData<P>,
+}
+
+impl<'a, 's, P, A: Automaton<P> + ?Sized>
+        Iterator for MatchesOverlapping<'a, 's, P, A> {
+    type Item = Match;
+
+    fn next(&mut self) -> Option<Match> {
+        if self.aut.has_match(self.si, self.outi) {
+            let m = self.aut.get_match(self.si, self.outi, self.texti);
+            self.outi += 1;
+            if !self.aut.has_match(self.si, self.outi) {
+                self.texti += 1;
+            }
+            return Some(m);
+        }
+
+        self.outi = 0;
+        if self.aut.start_bytes().len() == 1 {
+            let skip = skip_to_match(
+                self.aut, self.text, self.texti, self.si, skip1);
+            if let Some((texti, si)) = skip {
+                self.texti = texti;
+                self.si = si;
+                return self.next();
+            }
+        } else if self.aut.start_bytes().len() == 2 {
+            let skip = skip_to_match(
+                self.aut, self.text, self.texti, self.si, skip2);
+            if let Some((texti, si)) = skip {
+                self.texti = texti;
+                self.si = si;
+                return self.next();
+            }
+        } else if self.aut.start_bytes().len() == 3 {
+            let skip = skip_to_match(
+                self.aut, self.text, self.texti, self.si, skip3);
+            if let Some((texti, si)) = skip {
+                self.texti = texti;
+                self.si = si;
+                return self.next();
+            }
+        } else {
+            let step = step_to_match(self.aut, self.text, self.texti, self.si);
+            if let Some((texti, si)) = step {
+                self.texti = texti;
+                self.si = si;
+                return self.next();
+            }
+        }
+        None
+    }
+}
+
+/// An iterator of overlapping matches for streaming text.
+///
+/// This iterator yields `io::Result<Match>` values.
+///
+/// `'a` is the lifetime of the automaton, `R` is the type of the underlying
+/// `io::Read`er, and P is the type of the Automaton's pattern.
+#[derive(Debug)]
+pub struct StreamMatchesOverlapping<'a, R, P, A: 'a + Automaton<P> + ?Sized> {
+    aut: &'a A,
+    buf: io::BufReader<R>,
+    texti: usize,
+    si: StateIdx,
+    outi: usize,
+    _m: PhantomData<P>,
+}
+
+impl<'a, R: io::Read, P, A: Automaton<P> + ?Sized>
+        Iterator for StreamMatchesOverlapping<'a, R, P, A> {
+    type Item = io::Result<Match>;
+
+    fn next(&mut self) -> Option<io::Result<Match>> {
+        if self.aut.has_match(self.si, self.outi) {
+            let m = self.aut.get_match(self.si, self.outi, self.texti);
+            self.outi += 1;
+            if !self.aut.has_match(self.si, self.outi) {
+                self.texti += 1;
+            }
+            return Some(Ok(m));
+        }
+        let mut m = None;
+        let mut consumed = 0;
+        self.outi = 0;
+'LOOP:  loop {
+            self.buf.consume(consumed);
+            let bs = match self.buf.fill_buf() {
+                Err(err) => return Some(Err(err)),
+                Ok(bs) if bs.is_empty() => break,
+                Ok(bs) => bs,
+            };
+            consumed = bs.len(); // is shortened if we find a match
+            for (i, &b) in bs.iter().enumerate() {
+                self.si = self.aut.next_state(self.si, b);
+                if self.aut.has_match(self.si, self.outi) {
+                    m = Some(Ok(self.aut.get_match(
+                        self.si, self.outi, self.texti)));
+                    consumed = i + 1;
+                    self.outi += 1;
+                    if !self.aut.has_match(self.si, self.outi) {
+                        self.texti += 1;
+                    }
+                    break 'LOOP;
+                }
+                self.texti += 1;
+            }
+        }
+        self.buf.consume(consumed);
+        m
+    }
+}
diff --git a/rustc_deps/vendor/aho-corasick/src/full.rs b/rustc_deps/vendor/aho-corasick/src/full.rs
new file mode 100644
index 0000000..377940a
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/src/full.rs
@@ -0,0 +1,145 @@
+use std::fmt;
+use std::mem;
+
+use super::{
+    FAIL_STATE,
+    StateIdx, AcAutomaton, Transitions, Match,
+    usize_bytes, vec_bytes,
+};
+use super::autiter::Automaton;
+
+/// A complete Aho-Corasick automaton.
+///
+/// This uses a single transition matrix that permits each input character
+/// to move to the next state with a single lookup in the matrix.
+///
+/// This is as fast as it gets, but it is guaranteed to use a lot of memory.
+/// Namely, it will use at least `4 * 256 * #states`, where the number of
+/// states is capped at length of all patterns concatenated.
+#[derive(Clone)]
+pub struct FullAcAutomaton<P> {
+    pats: Vec<P>,
+    trans: Vec<StateIdx>,  // row-major, where states are rows
+    out: Vec<Vec<usize>>, // indexed by StateIdx
+    start_bytes: Vec<u8>,
+}
+
+impl<P: AsRef<[u8]>> FullAcAutomaton<P> {
+    /// Build a new expanded Aho-Corasick automaton from an existing
+    /// Aho-Corasick automaton.
+    pub fn new<T: Transitions>(ac: AcAutomaton<P, T>) -> FullAcAutomaton<P> {
+        let mut fac = FullAcAutomaton {
+            pats: vec![],
+            trans: vec![FAIL_STATE; 256 * ac.states.len()],
+            out: vec![vec![]; ac.states.len()],
+            start_bytes: vec![],
+        };
+        fac.build_matrix(&ac);
+        fac.pats = ac.pats;
+        fac.start_bytes = ac.start_bytes;
+        fac
+    }
+
+    #[doc(hidden)]
+    pub fn memory_usage(&self) -> usize {
+        self.pats.iter()
+            .map(|p| vec_bytes() + p.as_ref().len())
+            .sum::<usize>()
+        + (4 * self.trans.len())
+        + self.out.iter()
+              .map(|v| vec_bytes() + (usize_bytes() * v.len()))
+              .sum::<usize>()
+        + self.start_bytes.len()
+    }
+
+    #[doc(hidden)]
+    pub fn heap_bytes(&self) -> usize {
+        self.pats.iter()
+            .map(|p| mem::size_of::<P>() + p.as_ref().len())
+            .sum::<usize>()
+        + (4 * self.trans.len())
+        + self.out.iter()
+              .map(|v| vec_bytes() + (usize_bytes() * v.len()))
+              .sum::<usize>()
+        + self.start_bytes.len()
+    }
+
+    fn set(&mut self, si: StateIdx, i: u8, goto: StateIdx) {
+        let ns = self.num_states();
+        self.trans[i as usize * ns + si as usize] = goto;
+    }
+
+    #[doc(hidden)]
+    #[inline]
+    pub fn num_states(&self) -> usize {
+        self.out.len()
+    }
+}
+
+impl<P: AsRef<[u8]>> Automaton<P> for FullAcAutomaton<P> {
+    #[inline]
+    fn next_state(&self, si: StateIdx, i: u8) -> StateIdx {
+        let at = i as usize * self.num_states() + si as usize;
+        unsafe { *self.trans.get_unchecked(at) }
+    }
+
+    #[inline]
+    fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
+        let pati = self.out[si as usize][outi];
+        let patlen = self.pats[pati].as_ref().len();
+        let start = texti + 1 - patlen;
+        Match {
+            pati: pati,
+            start: start,
+            end: start + patlen,
+        }
+    }
+
+    #[inline]
+    fn has_match(&self, si: StateIdx, outi: usize) -> bool {
+        unsafe { outi < self.out.get_unchecked(si as usize).len() }
+    }
+
+    #[inline]
+    fn start_bytes(&self) -> &[u8] {
+        &self.start_bytes
+    }
+
+    #[inline]
+    fn patterns(&self) -> &[P] {
+        &self.pats
+    }
+
+    #[inline]
+    fn pattern(&self, i: usize) -> &P {
+        &self.pats[i]
+    }
+}
+
+impl<P: AsRef<[u8]>> FullAcAutomaton<P> {
+    fn build_matrix<T: Transitions>(&mut self, ac: &AcAutomaton<P, T>) {
+        for (si, s) in ac.states.iter().enumerate().skip(1) {
+            self.set_states(ac, si as StateIdx);
+            self.out[si].extend_from_slice(&s.out);
+        }
+    }
+
+    fn set_states<T: Transitions>(&mut self, ac: &AcAutomaton<P, T>, si: StateIdx) {
+        let current_state = &ac.states[si as usize];
+        let first_fail_state = current_state.fail;
+        current_state.for_each_transition(move |b, maybe_si| {
+            let goto = if maybe_si == FAIL_STATE {
+                ac.memoized_next_state(self, si, first_fail_state, b)
+            } else {
+                maybe_si
+            };
+            self.set(si, b, goto);
+        });
+    }
+}
+
+impl<P: AsRef<[u8]> + fmt::Debug> fmt::Debug for FullAcAutomaton<P> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "FullAcAutomaton({:?})", self.pats)
+    }
+}
diff --git a/rustc_deps/vendor/aho-corasick/src/lib.rs b/rustc_deps/vendor/aho-corasick/src/lib.rs
new file mode 100644
index 0000000..6ceb206
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/src/lib.rs
@@ -0,0 +1,1082 @@
+/*!
+An implementation of the
+[Aho-Corasick string search algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm).
+
+The Aho-Corasick algorithm is principally useful when you need to search many
+large texts for a fixed (possibly large) set of keywords. In particular, the
+Aho-Corasick algorithm preprocesses the set of keywords by constructing a
+finite state machine. The search phase is then a quick linear scan through the
+text. Each character in the search text causes a state transition in the
+automaton. Matches are reported when the automaton enters a match state.
+
+# Examples
+
+The main type exposed by this crate is `AcAutomaton`, which can be constructed
+from an iterator of pattern strings:
+
+```rust
+use aho_corasick::{Automaton, AcAutomaton};
+
+let aut = AcAutomaton::new(vec!["apple", "maple"]);
+
+// AcAutomaton also implements `FromIterator`:
+let aut: AcAutomaton<&str> = ["apple", "maple"].iter().cloned().collect();
+```
+
+Finding matches can be done with `find`:
+
+```rust
+use aho_corasick::{Automaton, AcAutomaton, Match};
+
+let aut = AcAutomaton::new(vec!["apple", "maple"]);
+let mut it = aut.find("I like maple apples.");
+assert_eq!(it.next(), Some(Match {
+    pati: 1,
+    start: 7,
+    end: 12,
+}));
+assert_eq!(it.next(), Some(Match {
+    pati: 0,
+    start: 13,
+    end: 18,
+}));
+assert_eq!(it.next(), None);
+```
+
+Use `find_overlapping` if you want to report all matches, even if they
+overlap with each other.
+
+```rust
+use aho_corasick::{Automaton, AcAutomaton, Match};
+
+let aut = AcAutomaton::new(vec!["abc", "a"]);
+let matches: Vec<_> = aut.find_overlapping("abc").collect();
+assert_eq!(matches, vec![
+    Match { pati: 1, start: 0, end: 1}, Match { pati: 0, start: 0, end: 3 },
+]);
+
+// Regular `find` will report only one match:
+let matches: Vec<_> = aut.find("abc").collect();
+assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]);
+```
+
+Finally, there are also methods for finding matches on *streams*. Namely, the
+search text does not have to live in memory. It's useful to run this on files
+that can't fit into memory:
+
+```no_run
+use std::fs::File;
+
+use aho_corasick::{Automaton, AcAutomaton};
+
+let aut = AcAutomaton::new(vec!["foo", "bar", "baz"]);
+let rdr = File::open("search.txt").unwrap();
+for m in aut.stream_find(rdr) {
+    let m = m.unwrap(); // could be an IO error
+    println!("Pattern '{}' matched at: ({}, {})",
+             aut.pattern(m.pati), m.start, m.end);
+}
+```
+
+There is also `stream_find_overlapping`, which is just like `find_overlapping`,
+but it operates on streams.
+
+Please see `dict-search.rs` in this crate's `examples` directory for a more
+complete example. It creates a large automaton from a dictionary and can do a
+streaming match over arbitrarily large data.
+
+# Memory usage
+
+A key aspect of an Aho-Corasick implementation is how the state transitions
+are represented. The easiest way to make the automaton fast is to store a
+sparse 256-slot map in each state. It maps an input byte to a state index.
+This makes the matching loop extremely fast, since it translates to a simple
+pointer read.
+
+The problem is that as the automaton accumulates more states, you end up paying
+a `256 * 4` (`4` is for the `u32` state index) byte penalty for every state
+regardless of how many transitions it has.
+
+To solve this, only states near the root of the automaton have this sparse
+map representation. States near the leaves of the automaton use a dense mapping
+that requires a linear scan.
+
+(The specific limit currently set is `3`, so that states with a depth less than
+or equal to `3` are less memory efficient. The result is that the memory usage
+of the automaton stops growing rapidly past ~60MB, even for automatons with
+thousands of patterns.)
+
+If you'd like to opt for the less-memory-efficient-but-faster version, then
+you can construct an `AcAutomaton` with a `Sparse` transition strategy:
+
+```rust
+use aho_corasick::{Automaton, AcAutomaton, Match, Sparse};
+
+let aut = AcAutomaton::<&str, Sparse>::with_transitions(vec!["abc", "a"]);
+let matches: Vec<_> = aut.find("abc").collect();
+assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]);
+```
+*/
+
+#![deny(missing_docs)]
+
+extern crate memchr;
+#[cfg(test)]
+extern crate quickcheck;
+#[cfg(test)]
+extern crate rand;
+
+use std::collections::VecDeque;
+use std::fmt;
+use std::iter::FromIterator;
+use std::mem;
+
+pub use self::autiter::{
+    Automaton, Match,
+    Matches, MatchesOverlapping, StreamMatches, StreamMatchesOverlapping,
+};
+pub use self::full::FullAcAutomaton;
+
+// We're specifying paths explicitly so that we can use
+// these modules simultaneously from `main.rs`.
+// Should probably make just make `main.rs` a separate crate.
+#[path = "autiter.rs"]
+mod autiter;
+#[path = "full.rs"]
+mod full;
+
+/// The integer type used for the state index.
+///
+/// Limiting this to 32 bit integers can have a big impact on memory usage
+/// when using the `Sparse` transition representation.
+pub type StateIdx = u32;
+
+// Constants for special state indexes.
+const FAIL_STATE: u32 = 0;
+const ROOT_STATE: u32 = 1;
+
+// Limit the depth at which we use a sparse alphabet map. Once the limit is
+// reached, a dense set is used (and lookup becomes O(n)).
+//
+// This does have a performance hit, but the (straight forward) alternative
+// is to have a `256 * 4` byte overhead for every state.
+// Given that Aho-Corasick is typically used for dictionary searching, this
+// can lead to dramatic memory bloat.
+//
+// This limit should only be increased at your peril. Namely, in the worst
+// case, `256^DENSE_DEPTH_THRESHOLD * 4` corresponds to the memory usage in
+// bytes. A value of `1` gives us a good balance. This is also a happy point
+// in the benchmarks. A value of `0` gives considerably worse times on certain
+// benchmarks (e.g., `ac_ten_one_prefix_byte_every_match`) than even a value
+// of `1`. A value of `2` is slightly better than `1` and it looks like gains
+// level off at that point with not much observable difference when set to
+// `3`.
+//
+// Why not make this user configurable? Well, it doesn't make much sense
+// because we pay for it with case analysis in the matching loop. Increasing it
+// doesn't have much impact on performance (outside of pathological cases?).
+//
+// N.B. Someone else seems to have discovered an alternative, but I haven't
+// grokked it yet: https://github.com/mischasan/aho-corasick
+const DENSE_DEPTH_THRESHOLD: u32 = 1;
+
+/// An Aho-Corasick finite automaton.
+///
+/// The type parameter `P` is the type of the pattern that was used to
+/// construct this AcAutomaton.
+#[derive(Clone)]
+pub struct AcAutomaton<P, T=Dense> {
+    pats: Vec<P>,
+    states: Vec<State<T>>,
+    start_bytes: Vec<u8>,
+}
+
+#[derive(Clone)]
+struct State<T> {
+    out: Vec<usize>,
+    fail: StateIdx,
+    goto: T,
+    depth: u32,
+}
+
+impl<P: AsRef<[u8]>> AcAutomaton<P> {
+    /// Create a new automaton from an iterator of patterns.
+    ///
+    /// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef`
+    /// trait.
+    pub fn new<I>(pats: I) -> AcAutomaton<P, Dense>
+            where I: IntoIterator<Item=P> {
+        AcAutomaton::with_transitions(pats)
+    }
+}
+
+impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
+    /// Create a new automaton from an iterator of patterns.
+    ///
+    /// This constructor allows one to choose the transition representation.
+    ///
+    /// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef`
+    /// trait.
+    pub fn with_transitions<I>(pats: I) -> AcAutomaton<P, T>
+            where I: IntoIterator<Item=P> {
+        AcAutomaton {
+            pats: vec![], // filled in later, avoid wrath of borrow checker
+            states: vec![State::new(0), State::new(0)], // empty and root
+            start_bytes: vec![], // also filled in later
+        }.build(pats.into_iter().collect())
+    }
+
+    /// Build out the entire automaton into a single matrix.
+    ///
+    /// This will make searching as fast as possible at the expense of using
+    /// at least `4 * 256 * #states` bytes of memory.
+    pub fn into_full(self) -> FullAcAutomaton<P> {
+        FullAcAutomaton::new(self)
+    }
+
+    #[doc(hidden)]
+    pub fn num_states(&self) -> usize {
+        self.states.len()
+    }
+
+    #[doc(hidden)]
+    pub fn heap_bytes(&self) -> usize {
+        self.pats.iter()
+            .map(|p| mem::size_of::<P>() + p.as_ref().len())
+            .sum::<usize>()
+        + self.states.iter()
+              .map(|s| mem::size_of::<State<T>>() + s.heap_bytes())
+              .sum::<usize>()
+        + self.start_bytes.len()
+    }
+
+    // The states of `full_automaton` should be set for all states < si
+    fn memoized_next_state(
+        &self,
+        full_automaton: &FullAcAutomaton<P>,
+        current_si: StateIdx,
+        mut si: StateIdx,
+        b: u8,
+    ) -> StateIdx {
+        loop {
+            if si < current_si {
+                return full_automaton.next_state(si, b);
+            }
+            let state = &self.states[si as usize];
+            let maybe_si = state.goto(b);
+            if maybe_si != FAIL_STATE {
+                return maybe_si;
+            } else {
+                si = state.fail;
+            }
+        }
+    }
+}
+
+impl<P: AsRef<[u8]>, T: Transitions> Automaton<P> for AcAutomaton<P, T> {
+    #[inline]
+    fn next_state(&self, mut si: StateIdx, b: u8) -> StateIdx {
+        loop {
+            let state = &self.states[si as usize];
+            let maybe_si = state.goto(b);
+            if maybe_si != FAIL_STATE {
+                si = maybe_si;
+                break;
+            } else {
+                si = state.fail;
+            }
+        }
+        si
+    }
+
+    #[inline]
+    fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
+        let pati = self.states[si as usize].out[outi];
+        let patlen = self.pats[pati].as_ref().len();
+        let start = texti + 1 - patlen;
+        Match {
+            pati: pati,
+            start: start,
+            end: start + patlen,
+        }
+    }
+
+    #[inline]
+    fn has_match(&self, si: StateIdx, outi: usize) -> bool {
+        outi < self.states[si as usize].out.len()
+    }
+
+    #[inline]
+    fn start_bytes(&self) -> &[u8] {
+        &self.start_bytes
+    }
+
+    #[inline]
+    fn patterns(&self) -> &[P] {
+        &self.pats
+    }
+
+    #[inline]
+    fn pattern(&self, i: usize) -> &P {
+        &self.pats[i]
+    }
+}
+
+// `(0..256).map(|b| b as u8)` optimizes poorly in debug builds so
+// we use this small explicit iterator instead
+struct AllBytesIter(i32);
+impl Iterator for AllBytesIter {
+    type Item = u8;
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.0 < 256 {
+            let b = self.0 as u8;
+            self.0 += 1;
+            Some(b)
+        } else {
+            None
+        }
+    }
+}
+
+impl AllBytesIter {
+    fn new() -> AllBytesIter {
+        AllBytesIter(0)
+    }
+}
+
+// Below contains code for *building* the automaton. It's a reasonably faithful
+// translation of the description/psuedo-code from:
+// http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
+
+impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
+    // This is the first phase and builds the initial keyword tree.
+    fn build(mut self, pats: Vec<P>) -> AcAutomaton<P, T> {
+        for (pati, pat) in pats.iter().enumerate() {
+            if pat.as_ref().is_empty() {
+                continue;
+            }
+            let mut previ = ROOT_STATE;
+            for &b in pat.as_ref() {
+                if self.states[previ as usize].goto(b) != FAIL_STATE {
+                    previ = self.states[previ as usize].goto(b);
+                } else {
+                    let depth = self.states[previ as usize].depth + 1;
+                    let nexti = self.add_state(State::new(depth));
+                    self.states[previ as usize].set_goto(b, nexti);
+                    previ = nexti;
+                }
+            }
+            self.states[previ as usize].out.push(pati);
+        }
+        {
+            let root_state = &mut self.states[ROOT_STATE as usize];
+            for c in AllBytesIter::new() {
+                if root_state.goto(c) == FAIL_STATE {
+                    root_state.set_goto(c, ROOT_STATE);
+                } else {
+                    self.start_bytes.push(c);
+                }
+            }
+        }
+        // If any of the start bytes are non-ASCII, then remove them all,
+        // because we don't want to be calling memchr on non-ASCII bytes.
+        // (Well, we could, but it requires being more clever. Simply using
+        // the prefix byte isn't good enough.)
+        if self.start_bytes.iter().any(|&b| b > 0x7F) {
+            self.start_bytes.clear();
+        }
+        self.pats = pats;
+        self.fill()
+    }
+
+    // The second phase that fills in the back links.
+    fn fill(mut self) -> AcAutomaton<P, T> {
+        // Fill up the queue with all non-root transitions out of the root
+        // node. Then proceed by breadth first traversal.
+        let mut q = VecDeque::new();
+        self.states[ROOT_STATE as usize].for_each_transition(|_, si| {
+            if si != ROOT_STATE {
+                q.push_front(si);
+            }
+        });
+
+        let mut transitions = Vec::new();
+
+        while let Some(si) = q.pop_back() {
+            self.states[si as usize].for_each_ok_transition(|c, u| {
+                transitions.push((c, u));
+                q.push_front(u);
+            });
+
+            for (c, u) in transitions.drain(..) {
+                let mut v = self.states[si as usize].fail;
+                loop {
+                    let state = &self.states[v as usize];
+                    if state.goto(c) == FAIL_STATE {
+                        v = state.fail;
+                    } else {
+                        break;
+                    }
+                }
+                let ufail = self.states[v as usize].goto(c);
+                self.states[u as usize].fail = ufail;
+
+                fn get_two<T>(xs: &mut [T], i: usize, j: usize) -> (&mut T, &mut T) {
+                    if i < j {
+                        let (before, after) = xs.split_at_mut(j);
+                        (&mut before[i], &mut after[0])
+                    } else {
+                        let (before, after) = xs.split_at_mut(i);
+                        (&mut after[0], &mut before[j])
+                    }
+                }
+
+                let (ufail_out, out) = get_two(&mut self.states, ufail as usize, u as usize);
+                out.out.extend_from_slice(&ufail_out.out);
+            }
+        }
+        self
+    }
+
+    fn add_state(&mut self, state: State<T>) -> StateIdx {
+        let i = self.states.len();
+        self.states.push(state);
+        i as StateIdx
+    }
+}
+
+impl<T: Transitions> State<T> {
+    fn new(depth: u32) -> State<T> {
+        State {
+            out: vec![],
+            fail: 1,
+            goto: Transitions::new(depth),
+            depth: depth,
+        }
+    }
+
+    fn goto(&self, b: u8) -> StateIdx {
+        self.goto.goto(b)
+    }
+
+    fn set_goto(&mut self, b: u8, si: StateIdx) {
+        self.goto.set_goto(b, si);
+    }
+
+    fn heap_bytes(&self) -> usize {
+        (self.out.len() * usize_bytes())
+        + self.goto.heap_bytes()
+    }
+
+    fn for_each_transition<F>(&self, f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        self.goto.for_each_transition(f)
+    }
+
+    fn for_each_ok_transition<F>(&self, f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        self.goto.for_each_ok_transition(f)
+    }
+}
+
+/// An abstraction over state transition strategies.
+///
+/// This is an attempt to let the caller choose the space/time trade offs
+/// used for state transitions.
+///
+/// (It's possible that this interface is merely good enough for just the two
+/// implementations in this crate.)
+pub trait Transitions {
+    /// Return a new state at the given depth.
+    fn new(depth: u32) -> Self;
+    /// Return the next state index given the next character.
+    fn goto(&self, alpha: u8) -> StateIdx;
+    /// Set the next state index for the character given.
+    fn set_goto(&mut self, alpha: u8, si: StateIdx);
+    /// The memory use in bytes (on the heap) of this set of transitions.
+    fn heap_bytes(&self) -> usize;
+
+    /// Iterates over each state
+    fn for_each_transition<F>(&self, mut f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        for b in AllBytesIter::new() {
+            f(b, self.goto(b));
+        }
+    }
+
+    /// Iterates over each non-fail state
+    fn for_each_ok_transition<F>(&self, mut f: F)
+    where
+        F: FnMut(u8, StateIdx),
+    {
+        self.for_each_transition(|b, si| {
+            if si != FAIL_STATE {
+                f(b, si);
+            }
+        });
+    }
+}
+
+/// State transitions that can be stored either sparsely or densely.
+///
+/// This uses less space but at the expense of slower matching.
+#[derive(Clone, Debug)]
+pub struct Dense(DenseChoice);
+
+#[derive(Clone, Debug)]
+enum DenseChoice {
+    Sparse(Box<Sparse>),
+    Dense(Vec<(u8, StateIdx)>),
+}
+
+impl Transitions for Dense {
+    fn new(depth: u32) -> Dense {
+        if depth <= DENSE_DEPTH_THRESHOLD {
+            Dense(DenseChoice::Sparse(Box::new(Sparse::new(depth))))
+        } else {
+            Dense(DenseChoice::Dense(vec![]))
+        }
+    }
+
+    fn goto(&self, b1: u8) -> StateIdx {
+        match self.0 {
+            DenseChoice::Sparse(ref m) => m.goto(b1),
+            DenseChoice::Dense(ref m) => {
+                for &(b2, si) in m {
+                    if b1 == b2 {
+                        return si;
+                    }
+                }
+                FAIL_STATE
+            }
+        }
+    }
+
+    fn set_goto(&mut self, b: u8, si: StateIdx) {
+        match self.0 {
+            DenseChoice::Sparse(ref mut m) => m.set_goto(b, si),
+            DenseChoice::Dense(ref mut m) => m.push((b, si)),
+        }
+    }
+
+    fn heap_bytes(&self) -> usize {
+        match self.0 {
+            DenseChoice::Sparse(_) => mem::size_of::<Sparse>(),
+            DenseChoice::Dense(ref m) => m.len() * (1 + 4),
+        }
+    }
+
+    fn for_each_transition<F>(&self, mut f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        match self.0 {
+            DenseChoice::Sparse(ref m) => m.for_each_transition(f),
+            DenseChoice::Dense(ref m) => {
+                let mut iter = m.iter();
+                let mut b = 0i32;
+                while let Some(&(next_b, next_si)) = iter.next() {
+                    while (b as u8) < next_b {
+                        f(b as u8, FAIL_STATE);
+                        b += 1;
+                    }
+                    f(b as u8, next_si);
+                    b += 1;
+                }
+                while b < 256 {
+                    f(b as u8, FAIL_STATE);
+                    b += 1;
+                }
+            }
+        }
+    }
+    fn for_each_ok_transition<F>(&self, mut f: F)
+    where
+        F: FnMut(u8, StateIdx),
+    {
+        match self.0 {
+            DenseChoice::Sparse(ref m) => m.for_each_ok_transition(f),
+            DenseChoice::Dense(ref m) => for &(b, si) in m {
+                f(b, si)
+            }
+        }
+    }
+}
+
+/// State transitions that are always sparse.
+///
+/// This can use enormous amounts of memory when there are many patterns,
+/// but matching is very fast.
+pub struct Sparse([StateIdx; 256]);
+
+impl Clone for Sparse {
+    fn clone(&self) -> Sparse {
+        Sparse(self.0)
+    }
+}
+
+impl fmt::Debug for Sparse {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Sparse").field(&&self.0[..]).finish()
+    }
+}
+
+impl Transitions for Sparse {
+    fn new(_: u32) -> Sparse {
+        Sparse([0; 256])
+    }
+
+    #[inline]
+    fn goto(&self, b: u8) -> StateIdx {
+        self.0[b as usize]
+    }
+
+    fn set_goto(&mut self, b: u8, si: StateIdx) {
+        self.0[b as usize] = si;
+    }
+
+    fn heap_bytes(&self) -> usize {
+        0
+    }
+}
+
+impl<S: AsRef<[u8]>> FromIterator<S> for AcAutomaton<S> {
+    /// Create an automaton from an iterator of strings.
+    fn from_iter<T>(it: T) -> AcAutomaton<S> where T: IntoIterator<Item=S> {
+        AcAutomaton::new(it)
+    }
+}
+
+// Provide some question debug impls for viewing automatons.
+// The custom impls mostly exist for special showing of sparse maps.
+
+impl<P: AsRef<[u8]> + fmt::Debug, T: Transitions>
+        fmt::Debug for AcAutomaton<P, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use std::iter::repeat;
+
+        try!(writeln!(f, "{}", repeat('-').take(79).collect::<String>()));
+        try!(writeln!(f, "Patterns: {:?}", self.pats));
+        for (i, state) in self.states.iter().enumerate().skip(1) {
+            try!(writeln!(f, "{:3}: {}", i, state.debug(i == 1)));
+        }
+        write!(f, "{}", repeat('-').take(79).collect::<String>())
+    }
+}
+
+impl<T: Transitions> State<T> {
+    fn debug(&self, root: bool) -> String {
+        format!("State {{ depth: {:?}, out: {:?}, fail: {:?}, goto: {{{}}} }}",
+                self.depth, self.out, self.fail, self.goto_string(root))
+    }
+
+    fn goto_string(&self, root: bool) -> String {
+        let mut goto = vec![];
+        for b in AllBytesIter::new() {
+            let si = self.goto(b);
+            if (!root && si == FAIL_STATE) || (root && si == ROOT_STATE) {
+                continue;
+            }
+            goto.push(format!("{} => {}", b as char, si));
+        }
+        goto.join(", ")
+    }
+}
+
+impl<T: Transitions> fmt::Debug for State<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.debug(false))
+    }
+}
+
+impl<T: Transitions> AcAutomaton<String, T> {
+    #[doc(hidden)]
+    pub fn dot(&self) -> String {
+        use std::fmt::Write;
+        let mut out = String::new();
+        macro_rules! w {
+            ($w:expr, $($tt:tt)*) => { {write!($w, $($tt)*)}.unwrap() }
+        }
+
+        w!(out, r#"
+digraph automaton {{
+    label=<<FONT POINT-SIZE="20">{}</FONT>>;
+    labelloc="l";
+    labeljust="l";
+    rankdir="LR";
+"#, self.pats.join(", "));
+        for (i, s) in self.states.iter().enumerate().skip(1) {
+            let i = i as u32;
+            if s.out.is_empty() {
+                w!(out, "    {};\n", i);
+            } else {
+                w!(out, "    {} [peripheries=2];\n", i);
+            }
+            w!(out, "    {} -> {} [style=dashed];\n", i, s.fail);
+            for b in AllBytesIter::new() {
+                let si = s.goto(b);
+                if si == FAIL_STATE || (i == ROOT_STATE && si == ROOT_STATE) {
+                    continue;
+                }
+                w!(out, "    {} -> {} [label={}];\n", i, si, b as char);
+            }
+        }
+        w!(out, "}}");
+        out
+    }
+}
+
+fn vec_bytes() -> usize {
+    usize_bytes() * 3
+}
+
+fn usize_bytes() -> usize {
+    let bits = usize::max_value().count_ones() as usize;
+    bits / 8
+}
+
+#[cfg(test)]
+mod tests {
+    use std::collections::HashSet;
+    use std::io;
+
+    use quickcheck::{Arbitrary, Gen, quickcheck};
+    use rand::Rng;
+
+    use super::{AcAutomaton, Automaton, Match, AllBytesIter};
+
+    fn aut_find<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        AcAutomaton::new(xs.to_vec()).find(&haystack).collect()
+    }
+
+    fn aut_finds<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        let cur = io::Cursor::new(haystack.as_bytes());
+        AcAutomaton::new(xs.to_vec())
+            .stream_find(cur).map(|r| r.unwrap()).collect()
+    }
+
+    fn aut_findf<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        AcAutomaton::new(xs.to_vec()).into_full().find(haystack).collect()
+    }
+
+    fn aut_findfs<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        let cur = io::Cursor::new(haystack.as_bytes());
+        AcAutomaton::new(xs.to_vec())
+            .into_full()
+            .stream_find(cur).map(|r| r.unwrap()).collect()
+    }
+
+    fn aut_findo<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        AcAutomaton::new(xs.to_vec()).find_overlapping(haystack).collect()
+    }
+
+    fn aut_findos<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        let cur = io::Cursor::new(haystack.as_bytes());
+        AcAutomaton::new(xs.to_vec())
+            .stream_find_overlapping(cur).map(|r| r.unwrap()).collect()
+    }
+
+    fn aut_findfo<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        AcAutomaton::new(xs.to_vec())
+            .into_full().find_overlapping(haystack).collect()
+    }
+
+    fn aut_findfos<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + AsRef<[u8]> {
+        let cur = io::Cursor::new(haystack.as_bytes());
+        AcAutomaton::new(xs.to_vec())
+            .into_full()
+            .stream_find_overlapping(cur).map(|r| r.unwrap()).collect()
+    }
+
+    #[test]
+    fn one_pattern_one_match() {
+        let ns = vec!["a"];
+        let hay = "za";
+        let matches = vec![
+            Match { pati: 0, start: 1, end: 2 },
+        ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn one_pattern_many_match() {
+        let ns = vec!["a"];
+        let hay = "zazazzzza";
+        let matches = vec![
+            Match { pati: 0, start: 1, end: 2 },
+            Match { pati: 0, start: 3, end: 4 },
+            Match { pati: 0, start: 8, end: 9 },
+        ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn one_longer_pattern_one_match() {
+        let ns = vec!["abc"];
+        let hay = "zazabcz";
+        let matches = vec![ Match { pati: 0, start: 3, end: 6 } ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn one_longer_pattern_many_match() {
+        let ns = vec!["abc"];
+        let hay = "zazabczzzzazzzabc";
+        let matches = vec![
+            Match { pati: 0, start: 3, end: 6 },
+            Match { pati: 0, start: 14, end: 17 },
+        ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_pattern_one_match() {
+        let ns = vec!["a", "b"];
+        let hay = "zb";
+        let matches = vec![ Match { pati: 1, start: 1, end: 2 } ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_pattern_many_match() {
+        let ns = vec!["a", "b"];
+        let hay = "zbzazzzzb";
+        let matches = vec![
+            Match { pati: 1, start: 1, end: 2 },
+            Match { pati: 0, start: 3, end: 4 },
+            Match { pati: 1, start: 8, end: 9 },
+        ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_longer_pattern_one_match() {
+        let ns = vec!["abc", "xyz"];
+        let hay = "zazxyzz";
+        let matches = vec![ Match { pati: 1, start: 3, end: 6 } ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_longer_pattern_many_match() {
+        let ns = vec!["abc", "xyz"];
+        let hay = "zazxyzzzzzazzzabcxyz";
+        let matches = vec![
+            Match { pati: 1, start: 3, end: 6 },
+            Match { pati: 0, start: 14, end: 17 },
+            Match { pati: 1, start: 17, end: 20 },
+        ];
+        assert_eq!(&aut_find(&ns, hay), &matches);
+        assert_eq!(&aut_finds(&ns, hay), &matches);
+        assert_eq!(&aut_findf(&ns, hay), &matches);
+        assert_eq!(&aut_findfs(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_longer_pattern_overlap_one_match() {
+        let ns = vec!["abc", "bc"];
+        let hay = "zazabcz";
+        let matches = vec![
+            Match { pati: 0, start: 3, end: 6 },
+            Match { pati: 1, start: 4, end: 6 },
+        ];
+        assert_eq!(&aut_findo(&ns, hay), &matches);
+        assert_eq!(&aut_findos(&ns, hay), &matches);
+        assert_eq!(&aut_findfo(&ns, hay), &matches);
+        assert_eq!(&aut_findfos(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_longer_pattern_overlap_one_match_reverse() {
+        let ns = vec!["abc", "bc"];
+        let hay = "xbc";
+        let matches = vec![ Match { pati: 1, start: 1, end: 3 } ];
+        assert_eq!(&aut_findo(&ns, hay), &matches);
+        assert_eq!(&aut_findos(&ns, hay), &matches);
+        assert_eq!(&aut_findfo(&ns, hay), &matches);
+        assert_eq!(&aut_findfos(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_longer_pattern_overlap_many_match() {
+        let ns = vec!["abc", "bc", "c"];
+        let hay = "zzzabczzzbczzzc";
+        let matches = vec![
+            Match { pati: 0, start: 3, end: 6 },
+            Match { pati: 1, start: 4, end: 6 },
+            Match { pati: 2, start: 5, end: 6 },
+            Match { pati: 1, start: 9, end: 11 },
+            Match { pati: 2, start: 10, end: 11 },
+            Match { pati: 2, start: 14, end: 15 },
+        ];
+        assert_eq!(&aut_findo(&ns, hay), &matches);
+        assert_eq!(&aut_findos(&ns, hay), &matches);
+        assert_eq!(&aut_findfo(&ns, hay), &matches);
+        assert_eq!(&aut_findfos(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn many_longer_pattern_overlap_many_match_reverse() {
+        let ns = vec!["abc", "bc", "c"];
+        let hay = "zzzczzzbczzzabc";
+        let matches = vec![
+            Match { pati: 2, start: 3, end: 4 },
+            Match { pati: 1, start: 7, end: 9 },
+            Match { pati: 2, start: 8, end: 9 },
+            Match { pati: 0, start: 12, end: 15 },
+            Match { pati: 1, start: 13, end: 15 },
+            Match { pati: 2, start: 14, end: 15 },
+        ];
+        assert_eq!(&aut_findo(&ns, hay), &matches);
+        assert_eq!(&aut_findos(&ns, hay), &matches);
+        assert_eq!(&aut_findfo(&ns, hay), &matches);
+        assert_eq!(&aut_findfos(&ns, hay), &matches);
+    }
+
+    #[test]
+    fn pattern_returns_original_type() {
+        let aut = AcAutomaton::new(vec!["apple", "maple"]);
+
+        // Explicitly given this type to assert that the thing returned
+        // from the function is our original type.
+        let pat: &str = aut.pattern(0);
+        assert_eq!(pat, "apple");
+
+        // Also check the return type of the `patterns` function.
+        let pats: &[&str] = aut.patterns();
+        assert_eq!(pats, &["apple", "maple"]);
+    }
+
+    // Quickcheck time.
+
+    // This generates very small ascii strings, which makes them more likely
+    // to interact in interesting ways with larger haystack strings.
+    #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+    pub struct SmallAscii(String);
+
+    impl Arbitrary for SmallAscii {
+        fn arbitrary<G: Gen>(g: &mut G) -> SmallAscii {
+            use std::char::from_u32;
+            SmallAscii((0..2)
+                       .map(|_| from_u32(g.gen_range(97, 123)).unwrap())
+                       .collect())
+        }
+
+        fn shrink(&self) -> Box<Iterator<Item=SmallAscii>> {
+            Box::new(self.0.shrink().map(SmallAscii))
+        }
+    }
+
+    impl From<SmallAscii> for String {
+        fn from(s: SmallAscii) -> String { s.0 }
+    }
+
+    impl AsRef<[u8]> for SmallAscii {
+        fn as_ref(&self) -> &[u8] { self.0.as_ref() }
+    }
+
+    // This is the same arbitrary impl as `String`, except it has a bias toward
+    // ASCII characters.
+    #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+    pub struct BiasAscii(String);
+
+    impl Arbitrary for BiasAscii {
+        fn arbitrary<G: Gen>(g: &mut G) -> BiasAscii {
+            use std::char::from_u32;
+            let size = { let s = g.size(); g.gen_range(0, s) };
+            let mut s = String::with_capacity(size);
+            for _ in 0..size {
+                if g.gen_bool(0.3) {
+                    s.push(char::arbitrary(g));
+                } else {
+                    for _ in 0..5 {
+                        s.push(from_u32(g.gen_range(97, 123)).unwrap());
+                    }
+                }
+            }
+            BiasAscii(s)
+        }
+
+        fn shrink(&self) -> Box<Iterator<Item=BiasAscii>> {
+            Box::new(self.0.shrink().map(BiasAscii))
+        }
+    }
+
+    fn naive_find<S>(xs: &[S], haystack: &str) -> Vec<Match>
+            where S: Clone + Into<String> {
+        let needles: Vec<String> =
+            xs.to_vec().into_iter().map(Into::into).collect();
+        let mut matches = vec![];
+        for hi in 0..haystack.len() {
+            for (pati, needle) in needles.iter().enumerate() {
+                let needle = needle.as_bytes();
+                if needle.len() == 0 || needle.len() > haystack.len() - hi {
+                    continue;
+                }
+                if needle == &haystack.as_bytes()[hi..hi+needle.len()] {
+                    matches.push(Match {
+                        pati: pati,
+                        start: hi,
+                        end: hi + needle.len(),
+                    });
+                }
+            }
+        }
+        matches
+    }
+
+    #[test]
+    fn qc_ac_equals_naive() {
+        fn prop(needles: Vec<SmallAscii>, haystack: BiasAscii) -> bool {
+            let aut_matches = aut_findo(&needles, &haystack.0);
+            let naive_matches = naive_find(&needles, &haystack.0);
+            // Ordering isn't always the same. I don't think we care, so do
+            // an unordered comparison.
+            let aset: HashSet<Match> = aut_matches.iter().cloned().collect();
+            let nset: HashSet<Match> = naive_matches.iter().cloned().collect();
+            aset == nset
+        }
+        quickcheck(prop as fn(Vec<SmallAscii>, BiasAscii) -> bool);
+    }
+
+
+    #[test]
+    fn all_bytes_iter() {
+        let all_bytes = AllBytesIter::new().collect::<Vec<_>>();
+        assert_eq!(all_bytes[0], 0);
+        assert_eq!(all_bytes[255], 255);
+        assert!(AllBytesIter::new().enumerate().all(|(i, b)| b as usize == i));
+    }
+}
diff --git a/rustc_deps/vendor/aho-corasick/src/main.rs b/rustc_deps/vendor/aho-corasick/src/main.rs
new file mode 100644
index 0000000..60562ac
--- /dev/null
+++ b/rustc_deps/vendor/aho-corasick/src/main.rs
@@ -0,0 +1,13 @@
+extern crate memchr;
+
+use std::env;
+
+use lib::AcAutomaton;
+
+#[allow(dead_code)]
+mod lib;
+
+fn main() {
+    let aut = AcAutomaton::new(env::args().skip(1));
+    println!("{}", aut.dot().trim());
+}
diff --git a/rustc_deps/vendor/regex-syntax/.cargo-checksum.json b/rustc_deps/vendor/regex-syntax/.cargo-checksum.json
new file mode 100644
index 0000000..eb9f3da
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".cargo_vcs_info.json":"f7ccd8813cd365a28b77cc37e598e15598f4aad06fbb0774c271e2989c645081","Cargo.toml":"dea8db95389ce01e09e0b1caed06c28fa4073c59df30e8042b6bdf387560f4b7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","benches/bench.rs":"4d09c75f457459f850877ee334a924f331c701a22fa19b1f7942c3504c8981f4","src/ast/mod.rs":"31825eaa0fdc0ae9939cf118f07c9a3ce7c0485065e0646df353a2d310ae5cd8","src/ast/parse.rs":"d1b5a837df7f7b09e5f6b70350407eeef56dfa5e6d27519fd903c07d16968fd1","src/ast/print.rs":"c7281fdec95b796c4e32393d3f750ab58cb5bea1dd77e87d4284c0ea0a304f1e","src/ast/visitor.rs":"493be4ba270f8cfeffe096b981947a12a5992542c1df1ed470e015f1c41ed081","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"ae638c6e6adcc7843dec98eb52b2dda2e5085a7c029a8d7f005ef40d35557617","src/hir/interval.rs":"3c2599c9c07149afb0770eca720ab66ed9599402ee58b34bf6709eac4c895239","src/hir/literal/mod.rs":"4fd26946232d056342a5052b4c84a28b6c0b956f57b4a4ff8fe64eb1b710aae5","src/hir/mod.rs":"07bdd0dc1c7c60194ab8a3242cb2fe58d5b51ba36d303d495dcd394726ea469e","src/hir/print.rs":"a7efad3703d1718de65c6657eff6be72a4e96bc3db8a56d08d2a96c0abdb99b8","src/hir/translate.rs":"ba2647fc8407ec88fc1705078b0783d2d7cbff44e54586f68dc54f90f0c548a9","src/hir/visitor.rs":"8e15e646c8c219fd1f4620fc3611dfbd0d63d598bc5c8bcbfb0106053134613c","src/lib.rs":"d1cbe98975034f18276e149bc42ce44d77623a62d53385b7d3a3fa1e2df9f383","src/parser.rs":"70e0386d373af3bc4e491c0371be06069a773cfb0476e44224702c3da643ce24","src/unicode.rs":"74e35b368555ad683284dc4795084e5b7f7cc9bb8fddd17bdd8e40a51588f43e","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"ad5413c1e4811d85ad845ccb21f12e6bbf33f7d048d0f91863b18da143eb49e8","src/unicode_tables/case_folding_simple.rs":"270a52df6dcb639cafaa9de563ff4dc88522fa9bfe7174f0b8c140d4208c71c7","src/unicode_tables/general_category.rs":"d0e8e05acf7563e426835502b2b510595a01a2739374ae54db29eefee642ed51","src/unicode_tables/mod.rs":"c395afbe606c4a9ef8656cd315b1ce2d5c1729fd60c99da8c6d661c49c47adf4","src/unicode_tables/perl_word.rs":"34050803ae07324c0bd1c976ffeac65df35ea8da3874ab391c997ece258130f3","src/unicode_tables/property_bool.rs":"12f0298e3cbaf7170ba8a9abaa4c1449ac9cc54a8126927e481f3aa350f42641","src/unicode_tables/property_names.rs":"3d1a6a69fb2780089e30919504f3b8314c71847bc89be24b98bc3fa96a5e1567","src/unicode_tables/property_values.rs":"2a86b2723a72f2c164f32b91907895edaf759a98e01b92f135fd2a70a62e5f00","src/unicode_tables/script.rs":"1584c2d3360fc331c0ae697903b59e7bd309d60a6920db8f6ef35d24a6846ec3","src/unicode_tables/script_extension.rs":"269b12f032940e098abcfa88234a3a0f0c74e036756bb3835d76fc197a73c54d"},"package":"fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e"}
\ No newline at end of file
diff --git a/rustc_deps/vendor/regex-syntax/.cargo_vcs_info.json b/rustc_deps/vendor/regex-syntax/.cargo_vcs_info.json
new file mode 100644
index 0000000..b24e8c9
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "770edd59b2c4d84dc40231e8648eeb65b2f0d94a"
+  }
+}
diff --git a/rustc_deps/vendor/regex-syntax/Cargo.toml b/rustc_deps/vendor/regex-syntax/Cargo.toml
new file mode 100644
index 0000000..c22b3c5
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/Cargo.toml
@@ -0,0 +1,23 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "regex-syntax"
+version = "0.6.3"
+authors = ["The Rust Project Developers"]
+description = "A regular expression parser."
+homepage = "https://github.com/rust-lang/regex"
+documentation = "https://docs.rs/regex-syntax"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/regex"
+[dependencies.ucd-util]
+version = "0.1.0"
diff --git a/rustc_deps/vendor/regex-syntax/LICENSE-APACHE b/rustc_deps/vendor/regex-syntax/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/rustc_deps/vendor/regex-syntax/LICENSE-MIT b/rustc_deps/vendor/regex-syntax/LICENSE-MIT
new file mode 100644
index 0000000..39d4bdb
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/rustc_deps/vendor/regex-syntax/benches/bench.rs b/rustc_deps/vendor/regex-syntax/benches/bench.rs
new file mode 100644
index 0000000..60aea9e
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/benches/bench.rs
@@ -0,0 +1,73 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(test)]
+
+extern crate regex_syntax;
+extern crate test;
+
+use regex_syntax::Parser;
+use test::Bencher;
+
+#[bench]
+fn parse_simple1(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"^bc(d|e)*$";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_simple2(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"'[a-zA-Z_][a-zA-Z0-9_]*(')\b";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_small1(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\p{L}|\p{N}|\s|.|\d";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_medium1(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\pL\p{Greek}\p{Hiragana}\p{Alphabetic}\p{Hebrew}\p{Arabic}";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_medium2(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\s\S\w\W\d\D";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_medium3(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\p{age:3.2}\p{hira}\p{scx:hira}\p{alphabetic}\p{sc:Greek}\pL";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_huge(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\p{L}{100}";
+        Parser::new().parse(re).unwrap()
+    });
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/ast/mod.rs b/rustc_deps/vendor/regex-syntax/src/ast/mod.rs
new file mode 100644
index 0000000..884fcfa
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/ast/mod.rs
@@ -0,0 +1,1515 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Defines an abstract syntax for regular expressions.
+*/
+
+use std::cmp::Ordering;
+use std::error;
+use std::fmt;
+
+pub use ast::visitor::{Visitor, visit};
+
+pub mod parse;
+pub mod print;
+mod visitor;
+
+/// An error that occurred while parsing a regular expression into an abstract
+/// syntax tree.
+///
+/// Note that note all ASTs represents a valid regular expression. For example,
+/// an AST is constructed without error for `\p{Quux}`, but `Quux` is not a
+/// valid Unicode property name. That particular error is reported when
+/// translating an AST to the high-level intermediate representation (`HIR`).
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Error {
+    /// The kind of error.
+    kind: ErrorKind,
+    /// The original pattern that the parser generated the error from. Every
+    /// span in an error is a valid range into this string.
+    pattern: String,
+    /// The span of this error.
+    span: Span,
+}
+
+impl Error {
+    /// Return the type of this error.
+    pub fn kind(&self) -> &ErrorKind {
+        &self.kind
+    }
+
+    /// The original pattern string in which this error occurred.
+    ///
+    /// Every span reported by this error is reported in terms of this string.
+    pub fn pattern(&self) -> &str {
+        &self.pattern
+    }
+
+    /// Return the span at which this error occurred.
+    pub fn span(&self) -> &Span {
+        &self.span
+    }
+
+    /// Return an auxiliary span. This span exists only for some errors that
+    /// benefit from being able to point to two locations in the original
+    /// regular expression. For example, "duplicate" errors will have the
+    /// main error position set to the duplicate occurrence while its
+    /// auxiliary span will be set to the initial occurrence.
+    pub fn auxiliary_span(&self) -> Option<&Span> {
+        use self::ErrorKind::*;
+        match self.kind {
+            FlagDuplicate { ref original } => Some(original),
+            FlagRepeatedNegation { ref original, .. } => Some(original),
+            GroupNameDuplicate { ref original, .. } => Some(original),
+            _ => None,
+        }
+    }
+}
+
+/// The type of an error that occurred while building an AST.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ErrorKind {
+    /// The capturing group limit was exceeded.
+    ///
+    /// Note that this represents a limit on the total number of capturing
+    /// groups in a regex and not necessarily the number of nested capturing
+    /// groups. That is, the nest limit can be low and it is still possible for
+    /// this error to occur.
+    CaptureLimitExceeded,
+    /// An invalid escape sequence was found in a character class set.
+    ClassEscapeInvalid,
+    /// An invalid character class range was found. An invalid range is any
+    /// range where the start is greater than the end.
+    ClassRangeInvalid,
+    /// An invalid range boundary was found in a character class. Range
+    /// boundaries must be a single literal codepoint, but this error indicates
+    /// that something else was found, such as a nested class.
+    ClassRangeLiteral,
+    /// An opening `[` was found with no corresponding closing `]`.
+    ClassUnclosed,
+    /// An empty decimal number was given where one was expected.
+    DecimalEmpty,
+    /// An invalid decimal number was given where one was expected.
+    DecimalInvalid,
+    /// A bracketed hex literal was empty.
+    EscapeHexEmpty,
+    /// A bracketed hex literal did not correspond to a Unicode scalar value.
+    EscapeHexInvalid,
+    /// An invalid hexadecimal digit was found.
+    EscapeHexInvalidDigit,
+    /// EOF was found before an escape sequence was completed.
+    EscapeUnexpectedEof,
+    /// An unrecognized escape sequence.
+    EscapeUnrecognized,
+    /// A dangling negation was used when setting flags, e.g., `i-`.
+    FlagDanglingNegation,
+    /// A flag was used twice, e.g., `i-i`.
+    FlagDuplicate {
+        /// The position of the original flag. The error position
+        /// points to the duplicate flag.
+        original: Span,
+    },
+    /// The negation operator was used twice, e.g., `-i-s`.
+    FlagRepeatedNegation {
+        /// The position of the original negation operator. The error position
+        /// points to the duplicate negation operator.
+        original: Span,
+    },
+    /// Expected a flag but got EOF, e.g., `(?`.
+    FlagUnexpectedEof,
+    /// Unrecognized flag, e.g., `a`.
+    FlagUnrecognized,
+    /// A duplicate capture name was found.
+    GroupNameDuplicate {
+        /// The position of the initial occurrence of the capture name. The
+        /// error position itself points to the duplicate occurrence.
+        original: Span,
+    },
+    /// A capture group name is empty, e.g., `(?P<>abc)`.
+    GroupNameEmpty,
+    /// An invalid character was seen for a capture group name. This includes
+    /// errors where the first character is a digit (even though subsequent
+    /// characters are allowed to be digits).
+    GroupNameInvalid,
+    /// A closing `>` could not be found for a capture group name.
+    GroupNameUnexpectedEof,
+    /// An unclosed group, e.g., `(ab`.
+    ///
+    /// The span of this error corresponds to the unclosed parenthesis.
+    GroupUnclosed,
+    /// An unopened group, e.g., `ab)`.
+    GroupUnopened,
+    /// The nest limit was exceeded. The limit stored here is the limit
+    /// configured in the parser.
+    NestLimitExceeded(u32),
+    /// The range provided in a counted repetition operator is invalid. The
+    /// range is invalid if the start is greater than the end.
+    RepetitionCountInvalid,
+    /// An opening `{` was found with no corresponding closing `}`.
+    RepetitionCountUnclosed,
+    /// A repetition operator was applied to a missing sub-expression. This
+    /// occurs, for example, in the regex consisting of just a `*` or even
+    /// `(?i)*`. It is, however, possible to create a repetition operating on
+    /// an empty sub-expression. For example, `()*` is still considered valid.
+    RepetitionMissing,
+    /// When octal support is disabled, this error is produced when an octal
+    /// escape is used. The octal escape is assumed to be an invocation of
+    /// a backreference, which is the common case.
+    UnsupportedBackreference,
+    /// When syntax similar to PCRE's look-around is used, this error is
+    /// returned. Some example syntaxes that are rejected include, but are
+    /// not necessarily limited to, `(?=re)`, `(?!re)`, `(?<=re)` and
+    /// `(?<!re)`. Note that all of these syntaxes are otherwise invalid; this
+    /// error is used to improve the user experience.
+    UnsupportedLookAround,
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        use self::ErrorKind::*;
+        match self.kind {
+            CaptureLimitExceeded => "capture group limit exceeded",
+            ClassEscapeInvalid => "invalid escape sequence in character class",
+            ClassRangeInvalid => "invalid character class range",
+            ClassRangeLiteral => "invalid range boundary, must be a literal",
+            ClassUnclosed => "unclosed character class",
+            DecimalEmpty => "empty decimal literal",
+            DecimalInvalid => "invalid decimal literal",
+            EscapeHexEmpty => "empty hexadecimal literal",
+            EscapeHexInvalid => "invalid hexadecimal literal",
+            EscapeHexInvalidDigit => "invalid hexadecimal digit",
+            EscapeUnexpectedEof => "unexpected eof (escape sequence)",
+            EscapeUnrecognized => "unrecognized escape sequence",
+            FlagDanglingNegation => "dangling flag negation operator",
+            FlagDuplicate{..} => "duplicate flag",
+            FlagRepeatedNegation{..} => "repeated negation",
+            FlagUnexpectedEof => "unexpected eof (flag)",
+            FlagUnrecognized => "unrecognized flag",
+            GroupNameDuplicate{..} => "duplicate capture group name",
+            GroupNameEmpty => "empty capture group name",
+            GroupNameInvalid => "invalid capture group name",
+            GroupNameUnexpectedEof => "unclosed capture group name",
+            GroupUnclosed => "unclosed group",
+            GroupUnopened => "unopened group",
+            NestLimitExceeded(_) => "nest limit exceeded",
+            RepetitionCountInvalid => "invalid repetition count range",
+            RepetitionCountUnclosed => "unclosed counted repetition",
+            RepetitionMissing => "repetition operator missing expression",
+            UnsupportedBackreference => "backreferences are not supported",
+            UnsupportedLookAround => "look-around is not supported",
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ::error::Formatter::from(self).fmt(f)
+    }
+}
+
+impl fmt::Display for ErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::ErrorKind::*;
+        match *self {
+            CaptureLimitExceeded => {
+                write!(f, "exceeded the maximum number of \
+                           capturing groups ({})", ::std::u32::MAX)
+            }
+            ClassEscapeInvalid => {
+                write!(f, "invalid escape sequence found in character class")
+            }
+            ClassRangeInvalid => {
+                write!(f, "invalid character class range, \
+                           the start must be <= the end")
+            }
+            ClassRangeLiteral => {
+                write!(f, "invalid range boundary, must be a literal")
+            }
+            ClassUnclosed => {
+                write!(f, "unclosed character class")
+            }
+            DecimalEmpty => {
+                write!(f, "decimal literal empty")
+            }
+            DecimalInvalid => {
+                write!(f, "decimal literal invalid")
+            }
+            EscapeHexEmpty => {
+                write!(f, "hexadecimal literal empty")
+            }
+            EscapeHexInvalid => {
+                write!(f, "hexadecimal literal is not a Unicode scalar value")
+            }
+            EscapeHexInvalidDigit => {
+                write!(f, "invalid hexadecimal digit")
+            }
+            EscapeUnexpectedEof => {
+                write!(f, "incomplete escape sequence, \
+                           reached end of pattern prematurely")
+            }
+            EscapeUnrecognized => {
+                write!(f, "unrecognized escape sequence")
+            }
+            FlagDanglingNegation => {
+                write!(f, "dangling flag negation operator")
+            }
+            FlagDuplicate{..} => {
+                write!(f, "duplicate flag")
+            }
+            FlagRepeatedNegation{..} => {
+                write!(f, "flag negation operator repeated")
+            }
+            FlagUnexpectedEof => {
+                write!(f, "expected flag but got end of regex")
+            }
+            FlagUnrecognized => {
+                write!(f, "unrecognized flag")
+            }
+            GroupNameDuplicate{..} => {
+                write!(f, "duplicate capture group name")
+            }
+            GroupNameEmpty => {
+                write!(f, "empty capture group name")
+            }
+            GroupNameInvalid => {
+                write!(f, "invalid capture group character")
+            }
+            GroupNameUnexpectedEof => {
+                write!(f, "unclosed capture group name")
+            }
+            GroupUnclosed => {
+                write!(f, "unclosed group")
+            }
+            GroupUnopened => {
+                write!(f, "unopened group")
+            }
+            NestLimitExceeded(limit) => {
+                write!(f, "exceed the maximum number of \
+                           nested parentheses/brackets ({})", limit)
+            }
+            RepetitionCountInvalid => {
+                write!(f, "invalid repetition count range, \
+                           the start must be <= the end")
+            }
+            RepetitionCountUnclosed => {
+                write!(f, "unclosed counted repetition")
+            }
+            RepetitionMissing => {
+                write!(f, "repetition operator missing expression")
+            }
+            UnsupportedBackreference => {
+                write!(f, "backreferences are not supported")
+            }
+            UnsupportedLookAround => {
+                write!(f, "look-around, including look-ahead and look-behind, \
+                           is not supported")
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
+/// Span represents the position information of a single AST item.
+///
+/// All span positions are absolute byte offsets that can be used on the
+/// original regular expression that was parsed.
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub struct Span {
+    /// The start byte offset.
+    pub start: Position,
+    /// The end byte offset.
+    pub end: Position,
+}
+
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Span({:?}, {:?})", self.start, self.end)
+    }
+}
+
+impl Ord for Span {
+    fn cmp(&self, other: &Span) -> Ordering {
+        (&self.start, &self.end).cmp(&(&other.start, &other.end))
+    }
+}
+
+impl PartialOrd for Span {
+    fn partial_cmp(&self, other: &Span) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+/// A single position in a regular expression.
+///
+/// A position encodes one half of a span, and include the byte offset, line
+/// number and column number.
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub struct Position {
+    /// The absolute offset of this position, starting at `0` from the
+    /// beginning of the regular expression pattern string.
+    pub offset: usize,
+    /// The line number, starting at `1`.
+    pub line: usize,
+    /// The approximate column number, starting at `1`.
+    pub column: usize,
+}
+
+impl fmt::Debug for Position {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "Position(o: {:?}, l: {:?}, c: {:?})",
+            self.offset, self.line, self.column)
+    }
+}
+
+impl Ord for Position {
+    fn cmp(&self, other: &Position) -> Ordering {
+        self.offset.cmp(&other.offset)
+    }
+}
+
+impl PartialOrd for Position {
+    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Span {
+    /// Create a new span with the given positions.
+    pub fn new(start: Position, end: Position) -> Span {
+        Span { start: start, end: end }
+    }
+
+    /// Create a new span using the given position as the start and end.
+    pub fn splat(pos: Position) -> Span {
+        Span::new(pos, pos)
+    }
+
+    /// Create a new span by replacing the starting the position with the one
+    /// given.
+    pub fn with_start(self, pos: Position) -> Span {
+        Span { start: pos, ..self }
+    }
+
+    /// Create a new span by replacing the ending the position with the one
+    /// given.
+    pub fn with_end(self, pos: Position) -> Span {
+        Span { end: pos, ..self }
+    }
+
+    /// Returns true if and only if this span occurs on a single line.
+    pub fn is_one_line(&self) -> bool {
+        self.start.line == self.end.line
+    }
+
+    /// Returns true if and only if this span is empty. That is, it points to
+    /// a single position in the concrete syntax of a regular expression.
+    pub fn is_empty(&self) -> bool {
+        self.start.offset == self.end.offset
+    }
+}
+
+impl Position {
+    /// Create a new position with the given information.
+    ///
+    /// `offset` is the absolute offset of the position, starting at `0` from
+    /// the beginning of the regular expression pattern string.
+    ///
+    /// `line` is the line number, starting at `1`.
+    ///
+    /// `column` is the approximate column number, starting at `1`.
+    pub fn new(offset: usize, line: usize, column: usize) -> Position {
+        Position { offset: offset, line: line, column: column }
+    }
+}
+
+/// An abstract syntax tree for a singular expression along with comments
+/// found.
+///
+/// Comments are not stored in the tree itself to avoid complexity. Each
+/// comment contains a span of precisely where it occurred in the original
+/// regular expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct WithComments {
+    /// The actual ast.
+    pub ast: Ast,
+    /// All comments found in the original regular expression.
+    pub comments: Vec<Comment>,
+}
+
+/// A comment from a regular expression with an associated span.
+///
+/// A regular expression can only contain comments when the `x` flag is
+/// enabled.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Comment {
+    /// The span of this comment, including the beginning `#` and ending `\n`.
+    pub span: Span,
+    /// The comment text, starting with the first character following the `#`
+    /// and ending with the last character preceding the `\n`.
+    pub comment: String,
+}
+
+/// An abstract syntax tree for a single regular expression.
+///
+/// An `Ast`'s `fmt::Display` implementation uses constant stack space and heap
+/// space proportional to the size of the `Ast`.
+///
+/// This type defines its own destructor that uses constant stack space and
+/// heap space proportional to the size of the `Ast`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Ast {
+    /// An empty regex that matches everything.
+    Empty(Span),
+    /// A set of flags, e.g., `(?is)`.
+    Flags(SetFlags),
+    /// A single character literal, which includes escape sequences.
+    Literal(Literal),
+    /// The "any character" class.
+    Dot(Span),
+    /// A single zero-width assertion.
+    Assertion(Assertion),
+    /// A single character class. This includes all forms of character classes
+    /// except for `.`. e.g., `\d`, `\pN`, `[a-z]` and `[[:alpha:]]`.
+    Class(Class),
+    /// A repetition operator applied to an arbitrary regular expression.
+    Repetition(Repetition),
+    /// A grouped regular expression.
+    Group(Group),
+    /// An alternation of regular expressions.
+    Alternation(Alternation),
+    /// A concatenation of regular expressions.
+    Concat(Concat),
+}
+
+impl Ast {
+    /// Return the span of this abstract syntax tree.
+    pub fn span(&self) -> &Span {
+        match *self {
+            Ast::Empty(ref span) => span,
+            Ast::Flags(ref x) => &x.span,
+            Ast::Literal(ref x) => &x.span,
+            Ast::Dot(ref span) => span,
+            Ast::Assertion(ref x) => &x.span,
+            Ast::Class(ref x) => x.span(),
+            Ast::Repetition(ref x) => &x.span,
+            Ast::Group(ref x) => &x.span,
+            Ast::Alternation(ref x) => &x.span,
+            Ast::Concat(ref x) => &x.span,
+        }
+    }
+
+    /// Return true if and only if this Ast is empty.
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            Ast::Empty(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if this AST has any (including possibly empty)
+    /// subexpressions.
+    fn has_subexprs(&self) -> bool {
+        match *self {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_) => false,
+            Ast::Class(_)
+            | Ast::Repetition(_)
+            | Ast::Group(_)
+            | Ast::Alternation(_)
+            | Ast::Concat(_) => true,
+        }
+    }
+}
+
+/// Print a display representation of this Ast.
+///
+/// This does not preserve any of the original whitespace formatting that may
+/// have originally been present in the concrete syntax from which this Ast
+/// was generated.
+///
+/// This implementation uses constant stack space and heap space proportional
+/// to the size of the `Ast`.
+impl fmt::Display for Ast {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use ast::print::Printer;
+        Printer::new().print(self, f)
+    }
+}
+
+/// An alternation of regular expressions.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Alternation {
+    /// The span of this alternation.
+    pub span: Span,
+    /// The alternate regular expressions.
+    pub asts: Vec<Ast>,
+}
+
+impl Alternation {
+    /// Return this alternation as an AST.
+    ///
+    /// If this alternation contains zero ASTs, then Ast::Empty is
+    /// returned. If this alternation contains exactly 1 AST, then the
+    /// corresponding AST is returned. Otherwise, Ast::Alternation is returned.
+    pub fn into_ast(mut self) -> Ast {
+        match self.asts.len() {
+            0 => Ast::Empty(self.span),
+            1 => self.asts.pop().unwrap(),
+            _ => Ast::Alternation(self),
+        }
+    }
+}
+
+/// A concatenation of regular expressions.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Concat {
+    /// The span of this concatenation.
+    pub span: Span,
+    /// The concatenation regular expressions.
+    pub asts: Vec<Ast>,
+}
+
+impl Concat {
+    /// Return this concatenation as an AST.
+    ///
+    /// If this concatenation contains zero ASTs, then Ast::Empty is
+    /// returned. If this concatenation contains exactly 1 AST, then the
+    /// corresponding AST is returned. Otherwise, Ast::Concat is returned.
+    pub fn into_ast(mut self) -> Ast {
+        match self.asts.len() {
+            0 => Ast::Empty(self.span),
+            1 => self.asts.pop().unwrap(),
+            _ => Ast::Concat(self),
+        }
+    }
+}
+
+/// A single literal expression.
+///
+/// A literal corresponds to a single Unicode scalar value. Literals may be
+/// represented in their literal form, e.g., `a` or in their escaped form,
+/// e.g., `\x61`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Literal {
+    /// The span of this literal.
+    pub span: Span,
+    /// The kind of this literal.
+    pub kind: LiteralKind,
+    /// The Unicode scalar value corresponding to this literal.
+    pub c: char,
+}
+
+impl Literal {
+    /// If this literal was written as a `\x` hex escape, then this returns
+    /// the corresponding byte value. Otherwise, this returns `None`.
+    pub fn byte(&self) -> Option<u8> {
+        let short_hex = LiteralKind::HexFixed(HexLiteralKind::X);
+        if self.c as u32 <= 255 && self.kind == short_hex {
+            Some(self.c as u8)
+        } else {
+            None
+        }
+    }
+}
+
+/// The kind of a single literal expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum LiteralKind {
+    /// The literal is written verbatim, e.g., `a` or `☃`.
+    Verbatim,
+    /// The literal is written as an escape because it is punctuation, e.g.,
+    /// `\*` or `\[`.
+    Punctuation,
+    /// The literal is written as an octal escape, e.g., `\141`.
+    Octal,
+    /// The literal is written as a hex code with a fixed number of digits
+    /// depending on the type of the escape, e.g., `\x61` or or `\u0061` or
+    /// `\U00000061`.
+    HexFixed(HexLiteralKind),
+    /// The literal is written as a hex code with a bracketed number of
+    /// digits. The only restriction is that the bracketed hex code must refer
+    /// to a valid Unicode scalar value.
+    HexBrace(HexLiteralKind),
+    /// The literal is written as a specially recognized escape, e.g., `\f`
+    /// or `\n`.
+    Special(SpecialLiteralKind),
+}
+
+/// The type of a special literal.
+///
+/// A special literal is a special escape sequence recognized by the regex
+/// parser, e.g., `\f` or `\n`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum SpecialLiteralKind {
+    /// Bell, spelled `\a` (`\x07`).
+    Bell,
+    /// Form feed, spelled `\f` (`\x0C`).
+    FormFeed,
+    /// Tab, spelled `\t` (`\x09`).
+    Tab,
+    /// Line feed, spelled `\n` (`\x0A`).
+    LineFeed,
+    /// Carriage return, spelled `\r` (`\x0D`).
+    CarriageReturn,
+    /// Vertical tab, spelled `\v` (`\x0B`).
+    VerticalTab,
+    /// Space, spelled `\ ` (`\x20`). Note that this can only appear when
+    /// parsing in verbose mode.
+    Space,
+}
+
+/// The type of a Unicode hex literal.
+///
+/// Note that all variants behave the same when used with brackets. They only
+/// differ when used without brackets in the number of hex digits that must
+/// follow.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum HexLiteralKind {
+    /// A `\x` prefix. When used without brackets, this form is limited to
+    /// two digits.
+    X,
+    /// A `\u` prefix. When used without brackets, this form is limited to
+    /// four digits.
+    UnicodeShort,
+    /// A `\U` prefix. When used without brackets, this form is limited to
+    /// eight digits.
+    UnicodeLong,
+}
+
+impl HexLiteralKind {
+    /// The number of digits that must be used with this literal form when
+    /// used without brackets. When used with brackets, there is no
+    /// restriction on the number of digits.
+    pub fn digits(&self) -> u32 {
+        match *self {
+            HexLiteralKind::X => 2,
+            HexLiteralKind::UnicodeShort => 4,
+            HexLiteralKind::UnicodeLong => 8,
+        }
+    }
+}
+
+/// A single character class expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Class {
+    /// A Unicode character class, e.g., `\pL` or `\p{Greek}`.
+    Unicode(ClassUnicode),
+    /// A perl character class, e.g., `\d` or `\W`.
+    Perl(ClassPerl),
+    /// A bracketed character class set, which may contain zero or more
+    /// character ranges and/or zero or more nested classes. e.g.,
+    /// `[a-zA-Z\pL]`.
+    Bracketed(ClassBracketed),
+}
+
+impl Class {
+    /// Return the span of this character class.
+    pub fn span(&self) -> &Span {
+        match *self {
+            Class::Perl(ref x) => &x.span,
+            Class::Unicode(ref x) => &x.span,
+            Class::Bracketed(ref x) => &x.span,
+        }
+    }
+}
+
+/// A Perl character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassPerl {
+    /// The span of this class.
+    pub span: Span,
+    /// The kind of Perl class.
+    pub kind: ClassPerlKind,
+    /// Whether the class is negated or not. e.g., `\d` is not negated but
+    /// `\D` is.
+    pub negated: bool,
+}
+
+/// The available Perl character classes.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassPerlKind {
+    /// Decimal numbers.
+    Digit,
+    /// Whitespace.
+    Space,
+    /// Word characters.
+    Word,
+}
+
+/// An ASCII character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassAscii {
+    /// The span of this class.
+    pub span: Span,
+    /// The kind of ASCII class.
+    pub kind: ClassAsciiKind,
+    /// Whether the class is negated or not. e.g., `[[:alpha:]]` is not negated
+    /// but `[[:^alpha:]]` is.
+    pub negated: bool,
+}
+
+/// The available ASCII character classes.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassAsciiKind {
+    /// `[0-9A-Za-z]`
+    Alnum,
+    /// `[A-Za-z]`
+    Alpha,
+    /// `[\x00-\x7F]`
+    Ascii,
+    /// `[ \t]`
+    Blank,
+    /// `[\x00-\x1F\x7F]`
+    Cntrl,
+    /// `[0-9]`
+    Digit,
+    /// `[!-~]`
+    Graph,
+    /// `[a-z]`
+    Lower,
+    /// `[ -~]`
+    Print,
+    /// `[!-/:-@\[-`{-~]`
+    Punct,
+    /// `[\t\n\v\f\r ]`
+    Space,
+    /// `[A-Z]`
+    Upper,
+    /// `[0-9A-Za-z_]`
+    Word,
+    /// `[0-9A-Fa-f]`
+    Xdigit,
+}
+
+impl ClassAsciiKind {
+    /// Return the corresponding ClassAsciiKind variant for the given name.
+    ///
+    /// The name given should correspond to the lowercase version of the
+    /// variant name. e.g., `cntrl` is the name for `ClassAsciiKind::Cntrl`.
+    ///
+    /// If no variant with the corresponding name exists, then `None` is
+    /// returned.
+    pub fn from_name(name: &str) -> Option<ClassAsciiKind> {
+        use self::ClassAsciiKind::*;
+        match name {
+            "alnum" => Some(Alnum),
+            "alpha" => Some(Alpha),
+            "ascii" => Some(Ascii),
+            "blank" => Some(Blank),
+            "cntrl" => Some(Cntrl),
+            "digit" => Some(Digit),
+            "graph" => Some(Graph),
+            "lower" => Some(Lower),
+            "print" => Some(Print),
+            "punct" => Some(Punct),
+            "space" => Some(Space),
+            "upper" => Some(Upper),
+            "word" => Some(Word),
+            "xdigit" => Some(Xdigit),
+            _ => None,
+        }
+    }
+}
+
+/// A Unicode character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassUnicode {
+    /// The span of this class.
+    pub span: Span,
+    /// Whether this class is negated or not.
+    ///
+    /// Note: be careful when using this attribute. This specifically refers
+    /// to whether the class is written as `\p` or `\P`, where the latter
+    /// is `negated = true`. However, it also possible to write something like
+    /// `\P{scx!=Katakana}` which is actually equivalent to
+    /// `\p{scx=Katakana}` and is therefore not actually negated even though
+    /// `negated = true` here. To test whether this class is truly negated
+    /// or not, use the `is_negated` method.
+    pub negated: bool,
+    /// The kind of Unicode class.
+    pub kind: ClassUnicodeKind,
+}
+
+impl ClassUnicode {
+    /// Returns true if this class has been negated.
+    ///
+    /// Note that this takes the Unicode op into account, if it's present.
+    /// e.g., `is_negated` for `\P{scx!=Katakana}` will return `false`.
+    pub fn is_negated(&self) -> bool {
+        match self.kind {
+            ClassUnicodeKind::NamedValue {
+                op: ClassUnicodeOpKind::NotEqual, ..
+            } => !self.negated,
+            _ => self.negated,
+        }
+    }
+}
+
+/// The available forms of Unicode character classes.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassUnicodeKind {
+    /// A one letter abbreviated class, e.g., `\pN`.
+    OneLetter(char),
+    /// A binary property, general category or script. The string may be
+    /// empty.
+    Named(String),
+    /// A property name and an associated value.
+    NamedValue {
+        /// The type of Unicode op used to associate `name` with `value`.
+        op: ClassUnicodeOpKind,
+        /// The property name (which may be empty).
+        name: String,
+        /// The property value (which may be empty).
+        value: String,
+    },
+}
+
+/// The type of op used in a Unicode character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassUnicodeOpKind {
+    /// A property set to a specific value, e.g., `\p{scx=Katakana}`.
+    Equal,
+    /// A property set to a specific value using a colon, e.g.,
+    /// `\p{scx:Katakana}`.
+    Colon,
+    /// A property that isn't a particular value, e.g., `\p{scx!=Katakana}`.
+    NotEqual,
+}
+
+impl ClassUnicodeOpKind {
+    /// Whether the op is an equality op or not.
+    pub fn is_equal(&self) -> bool {
+        match *self {
+            ClassUnicodeOpKind::Equal|ClassUnicodeOpKind::Colon => true,
+            _ => false,
+        }
+    }
+}
+
+/// A bracketed character class, e.g., `[a-z0-9]`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassBracketed {
+    /// The span of this class.
+    pub span: Span,
+    /// Whether this class is negated or not. e.g., `[a]` is not negated but
+    /// `[^a]` is.
+    pub negated: bool,
+    /// The type of this set. A set is either a normal union of things, e.g.,
+    /// `[abc]` or a result of applying set operations, e.g., `[\pL--c]`.
+    pub kind: ClassSet,
+}
+
+/// A character class set.
+///
+/// This type corresponds to the internal structure of a bracketed character
+/// class. That is, every bracketed character is one of two types: a union of
+/// items (literals, ranges, other bracketed classes) or a tree of binary set
+/// operations.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassSet {
+    /// An item, which can be a single literal, range, nested character class
+    /// or a union of items.
+    Item(ClassSetItem),
+    /// A single binary operation (i.e., &&, -- or ~~).
+    BinaryOp(ClassSetBinaryOp),
+}
+
+impl ClassSet {
+    /// Build a set from a union.
+    pub fn union(ast: ClassSetUnion) -> ClassSet {
+        ClassSet::Item(ClassSetItem::Union(ast))
+    }
+
+    /// Return the span of this character class set.
+    pub fn span(&self) -> &Span {
+        match *self {
+            ClassSet::Item(ref x) => x.span(),
+            ClassSet::BinaryOp(ref x) => &x.span,
+        }
+    }
+
+    /// Return true if and only if this class set is empty.
+    fn is_empty(&self) -> bool {
+        match *self {
+            ClassSet::Item(ClassSetItem::Empty(_)) => true,
+            _ => false,
+        }
+    }
+}
+
+/// A single component of a character class set.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassSetItem {
+    /// An empty item.
+    ///
+    /// Note that a bracketed character class cannot contain a single empty
+    /// item. Empty items can appear when using one of the binary operators.
+    /// For example, `[&&]` is the intersection of two empty classes.
+    Empty(Span),
+    /// A single literal.
+    Literal(Literal),
+    /// A range between two literals.
+    Range(ClassSetRange),
+    /// An ASCII character class, e.g., `[:alnum:]` or `[:punct:]`.
+    Ascii(ClassAscii),
+    /// A Unicode character class, e.g., `\pL` or `\p{Greek}`.
+    Unicode(ClassUnicode),
+    /// A perl character class, e.g., `\d` or `\W`.
+    Perl(ClassPerl),
+    /// A bracketed character class set, which may contain zero or more
+    /// character ranges and/or zero or more nested classes. e.g.,
+    /// `[a-zA-Z\pL]`.
+    Bracketed(Box<ClassBracketed>),
+    /// A union of items.
+    Union(ClassSetUnion),
+}
+
+impl ClassSetItem {
+    /// Return the span of this character class set item.
+    pub fn span(&self) -> &Span {
+        match *self {
+            ClassSetItem::Empty(ref span) => span,
+            ClassSetItem::Literal(ref x) => &x.span,
+            ClassSetItem::Range(ref x) => &x.span,
+            ClassSetItem::Ascii(ref x) => &x.span,
+            ClassSetItem::Perl(ref x) => &x.span,
+            ClassSetItem::Unicode(ref x) => &x.span,
+            ClassSetItem::Bracketed(ref x) => &x.span,
+            ClassSetItem::Union(ref x) => &x.span,
+        }
+    }
+}
+
+/// A single character class range in a set.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassSetRange {
+    /// The span of this range.
+    pub span: Span,
+    /// The start of this range.
+    pub start: Literal,
+    /// The end of this range.
+    pub end: Literal,
+}
+
+impl ClassSetRange {
+    /// Returns true if and only if this character class range is valid.
+    ///
+    /// The only case where a range is invalid is if its start is greater than
+    /// its end.
+    pub fn is_valid(&self) -> bool {
+        self.start.c <= self.end.c
+    }
+}
+
+/// A union of items inside a character class set.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassSetUnion {
+    /// The span of the items in this operation. e.g., the `a-z0-9` in
+    /// `[^a-z0-9]`
+    pub span: Span,
+    /// The sequence of items that make up this union.
+    pub items: Vec<ClassSetItem>,
+}
+
+impl ClassSetUnion {
+    /// Push a new item in this union.
+    ///
+    /// The ending position of this union's span is updated to the ending
+    /// position of the span of the item given. If the union is empty, then
+    /// the starting position of this union is set to the starting position
+    /// of this item.
+    ///
+    /// In other words, if you only use this method to add items to a union
+    /// and you set the spans on each item correctly, then you should never
+    /// need to adjust the span of the union directly.
+    pub fn push(&mut self, item: ClassSetItem) {
+        if self.items.is_empty() {
+            self.span.start = item.span().start;
+        }
+        self.span.end = item.span().end;
+        self.items.push(item);
+    }
+
+    /// Return this union as a character class set item.
+    ///
+    /// If this union contains zero items, then an empty union is
+    /// returned. If this concatenation contains exactly 1 item, then the
+    /// corresponding item is returned. Otherwise, ClassSetItem::Union is
+    /// returned.
+    pub fn into_item(mut self) -> ClassSetItem {
+        match self.items.len() {
+            0 => ClassSetItem::Empty(self.span),
+            1 => self.items.pop().unwrap(),
+            _ => ClassSetItem::Union(self),
+        }
+    }
+}
+
+/// A Unicode character class set operation.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassSetBinaryOp {
+    /// The span of this operation. e.g., the `a-z--[h-p]` in `[a-z--h-p]`.
+    pub span: Span,
+    /// The type of this set operation.
+    pub kind: ClassSetBinaryOpKind,
+    /// The left hand side of the operation.
+    pub lhs: Box<ClassSet>,
+    /// The right hand side of the operation.
+    pub rhs: Box<ClassSet>,
+}
+
+/// The type of a Unicode character class set operation.
+///
+/// Note that this doesn't explicitly represent union since there is no
+/// explicit union operator. Concatenation inside a character class corresponds
+/// to the union operation.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ClassSetBinaryOpKind {
+    /// The intersection of two sets, e.g., `\pN&&[a-z]`.
+    Intersection,
+    /// The difference of two sets, e.g., `\pN--[0-9]`.
+    Difference,
+    /// The symmetric difference of two sets. The symmetric difference is the
+    /// set of elements belonging to one but not both sets.
+    /// e.g., `[\pL~~[:ascii:]]`.
+    SymmetricDifference,
+}
+
+/// A single zero-width assertion.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Assertion {
+    /// The span of this assertion.
+    pub span: Span,
+    /// The assertion kind, e.g., `\b` or `^`.
+    pub kind: AssertionKind,
+}
+
+/// An assertion kind.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum AssertionKind {
+    /// `^`
+    StartLine,
+    /// `$`
+    EndLine,
+    /// `\A`
+    StartText,
+    /// `\z`
+    EndText,
+    /// `\b`
+    WordBoundary,
+    /// `\B`
+    NotWordBoundary,
+}
+
+/// A repetition operation applied to a regular expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Repetition {
+    /// The span of this operation.
+    pub span: Span,
+    /// The actual operation.
+    pub op: RepetitionOp,
+    /// Whether this operation was applied greedily or not.
+    pub greedy: bool,
+    /// The regular expression under repetition.
+    pub ast: Box<Ast>,
+}
+
+/// The repetition operator itself.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct RepetitionOp {
+    /// The span of this operator. This includes things like `+`, `*?` and
+    /// `{m,n}`.
+    pub span: Span,
+    /// The type of operation.
+    pub kind: RepetitionKind,
+}
+
+/// The kind of a repetition operator.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum RepetitionKind {
+    /// `?`
+    ZeroOrOne,
+    /// `*`
+    ZeroOrMore,
+    /// `+`
+    OneOrMore,
+    /// `{m,n}`
+    Range(RepetitionRange),
+}
+
+/// A range repetition operator.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum RepetitionRange {
+    /// `{m}`
+    Exactly(u32),
+    /// `{m,}`
+    AtLeast(u32),
+    /// `{m,n}`
+    Bounded(u32, u32),
+}
+
+impl RepetitionRange {
+    /// Returns true if and only if this repetition range is valid.
+    ///
+    /// The only case where a repetition range is invalid is if it is bounded
+    /// and its start is greater than its end.
+    pub fn is_valid(&self) -> bool {
+        match *self {
+            RepetitionRange::Bounded(s, e) if s > e => false,
+            _ => true,
+        }
+    }
+}
+
+/// A grouped regular expression.
+///
+/// This includes both capturing and non-capturing groups. This does **not**
+/// include flag-only groups like `(?is)`, but does contain any group that
+/// contains a sub-expression, e.g., `(a)`, `(?P<name>a)`, `(?:a)` and
+/// `(?is:a)`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Group {
+    /// The span of this group.
+    pub span: Span,
+    /// The kind of this group.
+    pub kind: GroupKind,
+    /// The regular expression in this group.
+    pub ast: Box<Ast>,
+}
+
+impl Group {
+    /// If this group is non-capturing, then this returns the (possibly empty)
+    /// set of flags. Otherwise, `None` is returned.
+    pub fn flags(&self) -> Option<&Flags> {
+        match self.kind {
+            GroupKind::NonCapturing(ref flags) => Some(flags),
+            _ => None,
+        }
+    }
+
+    /// Returns true if and only if this group is capturing.
+    pub fn is_capturing(&self) -> bool {
+        match self.kind {
+            GroupKind::CaptureIndex(_) | GroupKind::CaptureName(_) => true,
+            GroupKind::NonCapturing(_) => false,
+        }
+    }
+
+    /// Returns the capture index of this group, if this is a capturing group.
+    ///
+    /// This returns a capture index precisely when `is_capturing` is `true`.
+    pub fn capture_index(&self) -> Option<u32> {
+        match self.kind {
+            GroupKind::CaptureIndex(i) => Some(i),
+            GroupKind::CaptureName(ref x) => Some(x.index),
+            GroupKind::NonCapturing(_) => None,
+        }
+    }
+}
+
+/// The kind of a group.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum GroupKind {
+    /// `(a)`
+    CaptureIndex(u32),
+    /// `(?P<name>a)`
+    CaptureName(CaptureName),
+    /// `(?:a)` and `(?i:a)`
+    NonCapturing(Flags),
+}
+
+/// A capture name.
+///
+/// This corresponds to the name itself between the angle brackets in, e.g.,
+/// `(?P<foo>expr)`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct CaptureName {
+    /// The span of this capture name.
+    pub span: Span,
+    /// The capture name.
+    pub name: String,
+    /// The capture index.
+    pub index: u32,
+}
+
+/// A group of flags that is not applied to a particular regular expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct SetFlags {
+    /// The span of these flags, including the grouping parentheses.
+    pub span: Span,
+    /// The actual sequence of flags.
+    pub flags: Flags,
+}
+
+/// A group of flags.
+///
+/// This corresponds only to the sequence of flags themselves, e.g., `is-u`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Flags {
+    /// The span of this group of flags.
+    pub span: Span,
+    /// A sequence of flag items. Each item is either a flag or a negation
+    /// operator.
+    pub items: Vec<FlagsItem>,
+}
+
+impl Flags {
+    /// Add the given item to this sequence of flags.
+    ///
+    /// If the item was added successfully, then `None` is returned. If the
+    /// given item is a duplicate, then `Some(i)` is returned, where
+    /// `items[i].kind == item.kind`.
+    pub fn add_item(&mut self, item: FlagsItem) -> Option<usize> {
+        for (i, x) in self.items.iter().enumerate() {
+            if x.kind == item.kind {
+                return Some(i);
+            }
+        }
+        self.items.push(item);
+        None
+    }
+
+    /// Returns the state of the given flag in this set.
+    ///
+    /// If the given flag is in the set but is negated, then `Some(false)` is
+    /// returned.
+    ///
+    /// If the given flag is in the set and is not negated, then `Some(true)`
+    /// is returned.
+    ///
+    /// Otherwise, `None` is returned.
+    pub fn flag_state(&self, flag: Flag) -> Option<bool> {
+        let mut negated = false;
+        for x in &self.items {
+            match x.kind {
+                FlagsItemKind::Negation => {
+                    negated = true;
+                }
+                FlagsItemKind::Flag(ref xflag) if xflag == &flag => {
+                    return Some(!negated);
+                }
+                _ => {}
+            }
+        }
+        None
+    }
+}
+
+/// A single item in a group of flags.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct FlagsItem {
+    /// The span of this item.
+    pub span: Span,
+    /// The kind of this item.
+    pub kind: FlagsItemKind,
+}
+
+/// The kind of an item in a group of flags.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum FlagsItemKind {
+    /// A negation operator applied to all subsequent flags in the enclosing
+    /// group.
+    Negation,
+    /// A single flag in a group.
+    Flag(Flag),
+}
+
+impl FlagsItemKind {
+    /// Returns true if and only if this item is a negation operator.
+    pub fn is_negation(&self) -> bool {
+        match *self {
+            FlagsItemKind::Negation => true,
+            _ => false,
+        }
+    }
+}
+
+/// A single flag.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Flag {
+    /// `i`
+    CaseInsensitive,
+    /// `m`
+    MultiLine,
+    /// `s`
+    DotMatchesNewLine,
+    /// `U`
+    SwapGreed,
+    /// `u`
+    Unicode,
+    /// `x`
+    IgnoreWhitespace,
+}
+
+/// A custom `Drop` impl is used for `Ast` such that it uses constant stack
+/// space but heap space proportional to the depth of the `Ast`.
+impl Drop for Ast {
+    fn drop(&mut self) {
+        use std::mem;
+
+        match *self {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_)
+            // Classes are recursive, so they get their own Drop impl.
+            | Ast::Class(_) => return,
+            Ast::Repetition(ref x) if !x.ast.has_subexprs() => return,
+            Ast::Group(ref x) if !x.ast.has_subexprs() => return,
+            Ast::Alternation(ref x) if x.asts.is_empty() => return,
+            Ast::Concat(ref x) if x.asts.is_empty() => return,
+            _ => {}
+        }
+
+        let empty_span = || Span::splat(Position::new(0, 0, 0));
+        let empty_ast = || Ast::Empty(empty_span());
+        let mut stack = vec![mem::replace(self, empty_ast())];
+        while let Some(mut ast) = stack.pop() {
+            match ast {
+                Ast::Empty(_)
+                | Ast::Flags(_)
+                | Ast::Literal(_)
+                | Ast::Dot(_)
+                | Ast::Assertion(_)
+                // Classes are recursive, so they get their own Drop impl.
+                | Ast::Class(_) => {}
+                Ast::Repetition(ref mut x) => {
+                    stack.push(mem::replace(&mut x.ast, empty_ast()));
+                }
+                Ast::Group(ref mut x) => {
+                    stack.push(mem::replace(&mut x.ast, empty_ast()));
+                }
+                Ast::Alternation(ref mut x) => {
+                    stack.extend(x.asts.drain(..));
+                }
+                Ast::Concat(ref mut x) => {
+                    stack.extend(x.asts.drain(..));
+                }
+            }
+        }
+    }
+}
+
+/// A custom `Drop` impl is used for `ClassSet` such that it uses constant
+/// stack space but heap space proportional to the depth of the `ClassSet`.
+impl Drop for ClassSet {
+    fn drop(&mut self) {
+        use std::mem;
+
+        match *self {
+            ClassSet::Item(ref item) => {
+                match *item {
+                    ClassSetItem::Empty(_)
+                    | ClassSetItem::Literal(_)
+                    | ClassSetItem::Range(_)
+                    | ClassSetItem::Ascii(_)
+                    | ClassSetItem::Unicode(_)
+                    | ClassSetItem::Perl(_) => return,
+                    ClassSetItem::Bracketed(ref x) => {
+                        if x.kind.is_empty() {
+                            return;
+                        }
+                    }
+                    ClassSetItem::Union(ref x) => {
+                        if x.items.is_empty() {
+                            return;
+                        }
+                    }
+                }
+            }
+            ClassSet::BinaryOp(ref op) => {
+                if op.lhs.is_empty() && op.rhs.is_empty() {
+                    return;
+                }
+            }
+        }
+
+        let empty_span = || Span::splat(Position::new(0, 0, 0));
+        let empty_set = || ClassSet::Item(ClassSetItem::Empty(empty_span()));
+        let mut stack = vec![mem::replace(self, empty_set())];
+        while let Some(mut set) = stack.pop() {
+            match set {
+                ClassSet::Item(ref mut item) => {
+                    match *item {
+                        ClassSetItem::Empty(_)
+                        | ClassSetItem::Literal(_)
+                        | ClassSetItem::Range(_)
+                        | ClassSetItem::Ascii(_)
+                        | ClassSetItem::Unicode(_)
+                        | ClassSetItem::Perl(_) => {}
+                        ClassSetItem::Bracketed(ref mut x) => {
+                            stack.push(mem::replace(&mut x.kind, empty_set()));
+                        }
+                        ClassSetItem::Union(ref mut x) => {
+                            stack.extend(
+                                x.items.drain(..).map(ClassSet::Item));
+                        }
+                    }
+                }
+                ClassSet::BinaryOp(ref mut op) => {
+                    stack.push(mem::replace(&mut op.lhs, empty_set()));
+                    stack.push(mem::replace(&mut op.rhs, empty_set()));
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    // We use a thread with an explicit stack size to test that our destructor
+    // for Ast can handle arbitrarily sized expressions in constant stack
+    // space. In case we run on a platform without threads (WASM?), we limit
+    // this test to Windows/Unix.
+    #[test]
+    #[cfg(any(unix, windows))]
+    fn no_stack_overflow_on_drop() {
+        use std::thread;
+
+        let run = || {
+            let span = || Span::splat(Position::new(0, 0, 0));
+            let mut ast = Ast::Empty(span());
+            for i in 0..200 {
+                ast = Ast::Group(Group {
+                    span: span(),
+                    kind: GroupKind::CaptureIndex(i),
+                    ast: Box::new(ast),
+                });
+            }
+            assert!(!ast.is_empty());
+        };
+
+        // We run our test on a thread with a small stack size so we can
+        // force the issue more easily.
+        thread::Builder::new()
+            .stack_size(1<<10)
+            .spawn(run)
+            .unwrap()
+            .join()
+            .unwrap();
+    }
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/ast/parse.rs b/rustc_deps/vendor/regex-syntax/src/ast/parse.rs
new file mode 100644
index 0000000..b73baee
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/ast/parse.rs
@@ -0,0 +1,5365 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+This module provides a regular expression parser.
+*/
+
+use std::borrow::Borrow;
+use std::cell::{Cell, RefCell};
+use std::mem;
+use std::result;
+
+use ast::{self, Ast, Position, Span};
+use either::Either;
+
+use is_meta_character;
+
+type Result<T> = result::Result<T, ast::Error>;
+
+/// A primitive is an expression with no sub-expressions. This includes
+/// literals, assertions and non-set character classes. This representation
+/// is used as intermediate state in the parser.
+///
+/// This does not include ASCII character classes, since they can only appear
+/// within a set character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+enum Primitive {
+    Literal(ast::Literal),
+    Assertion(ast::Assertion),
+    Dot(Span),
+    Perl(ast::ClassPerl),
+    Unicode(ast::ClassUnicode),
+}
+
+impl Primitive {
+    /// Return the span of this primitive.
+    fn span(&self) -> &Span {
+        match *self {
+            Primitive::Literal(ref x) => &x.span,
+            Primitive::Assertion(ref x) => &x.span,
+            Primitive::Dot(ref span) => span,
+            Primitive::Perl(ref x) => &x.span,
+            Primitive::Unicode(ref x) => &x.span,
+        }
+    }
+
+    /// Convert this primitive into a proper AST.
+    fn into_ast(self) -> Ast {
+        match self {
+            Primitive::Literal(lit) => Ast::Literal(lit),
+            Primitive::Assertion(assert) => Ast::Assertion(assert),
+            Primitive::Dot(span) => Ast::Dot(span),
+            Primitive::Perl(cls) => Ast::Class(ast::Class::Perl(cls)),
+            Primitive::Unicode(cls) => Ast::Class(ast::Class::Unicode(cls)),
+        }
+    }
+
+    /// Convert this primitive into an item in a character class.
+    ///
+    /// If this primitive is not a legal item (i.e., an assertion or a dot),
+    /// then return an error.
+    fn into_class_set_item<P: Borrow<Parser>>(
+        self,
+        p: &ParserI<P>,
+    ) -> Result<ast::ClassSetItem> {
+        use ast::ClassSetItem;
+        use self::Primitive::*;
+
+        match self {
+            Literal(lit) => Ok(ClassSetItem::Literal(lit)),
+            Perl(cls) => Ok(ClassSetItem::Perl(cls)),
+            Unicode(cls) => Ok(ClassSetItem::Unicode(cls)),
+            x => Err(p.error(*x.span(), ast::ErrorKind::ClassEscapeInvalid)),
+        }
+    }
+
+    /// Convert this primitive into a literal in a character class. In
+    /// particular, literals are the only valid items that can appear in
+    /// ranges.
+    ///
+    /// If this primitive is not a legal item (i.e., a class, assertion or a
+    /// dot), then return an error.
+    fn into_class_literal<P: Borrow<Parser>>(
+        self,
+        p: &ParserI<P>,
+    ) -> Result<ast::Literal> {
+        use self::Primitive::*;
+
+        match self {
+            Literal(lit) => Ok(lit),
+            x => Err(p.error(*x.span(), ast::ErrorKind::ClassRangeLiteral)),
+        }
+    }
+}
+
+/// Returns true if the given character is a hexadecimal digit.
+fn is_hex(c: char) -> bool {
+    ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
+}
+
+/// Returns true if the given character is a valid in a capture group name.
+///
+/// If `first` is true, then `c` is treated as the first character in the
+/// group name (which is not allowed to be a digit).
+fn is_capture_char(c: char, first: bool) -> bool {
+    c == '_' || (!first && c >= '0' && c <= '9')
+    || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+/// A builder for a regular expression parser.
+///
+/// This builder permits modifying configuration options for the parser.
+#[derive(Clone, Debug)]
+pub struct ParserBuilder {
+    ignore_whitespace: bool,
+    nest_limit: u32,
+    octal: bool,
+}
+
+impl Default for ParserBuilder {
+    fn default() -> ParserBuilder {
+        ParserBuilder::new()
+    }
+}
+
+impl ParserBuilder {
+    /// Create a new parser builder with a default configuration.
+    pub fn new() -> ParserBuilder {
+        ParserBuilder {
+            ignore_whitespace: false,
+            nest_limit: 250,
+            octal: false,
+        }
+    }
+
+    /// Build a parser from this configuration with the given pattern.
+    pub fn build(&self) -> Parser {
+        Parser {
+            pos: Cell::new(Position { offset: 0, line: 1, column: 1 }),
+            capture_index: Cell::new(0),
+            nest_limit: self.nest_limit,
+            octal: self.octal,
+            initial_ignore_whitespace: self.ignore_whitespace,
+            ignore_whitespace: Cell::new(self.ignore_whitespace),
+            comments: RefCell::new(vec![]),
+            stack_group: RefCell::new(vec![]),
+            stack_class: RefCell::new(vec![]),
+            capture_names: RefCell::new(vec![]),
+            scratch: RefCell::new(String::new()),
+        }
+    }
+
+    /// Set the nesting limit for this parser.
+    ///
+    /// The nesting limit controls how deep the abstract syntax tree is allowed
+    /// to be. If the AST exceeds the given limit (e.g., with too many nested
+    /// groups), then an error is returned by the parser.
+    ///
+    /// The purpose of this limit is to act as a heuristic to prevent stack
+    /// overflow for consumers that do structural induction on an `Ast` using
+    /// explicit recursion. While this crate never does this (instead using
+    /// constant stack space and moving the call stack to the heap), other
+    /// crates may.
+    ///
+    /// This limit is not checked until the entire Ast is parsed. Therefore,
+    /// if callers want to put a limit on the amount of heap space used, then
+    /// they should impose a limit on the length, in bytes, of the concrete
+    /// pattern string. In particular, this is viable since this parser
+    /// implementation will limit itself to heap space proportional to the
+    /// lenth of the pattern string.
+    ///
+    /// Note that a nest limit of `0` will return a nest limit error for most
+    /// patterns but not all. For example, a nest limit of `0` permits `a` but
+    /// not `ab`, since `ab` requires a concatenation, which results in a nest
+    /// depth of `1`. In general, a nest limit is not something that manifests
+    /// in an obvious way in the concrete syntax, therefore, it should not be
+    /// used in a granular way.
+    pub fn nest_limit(&mut self, limit: u32) -> &mut ParserBuilder {
+        self.nest_limit = limit;
+        self
+    }
+
+    /// Whether to support octal syntax or not.
+    ///
+    /// Octal syntax is a little-known way of uttering Unicode codepoints in
+    /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+    /// `\141` are all equivalent regular expressions, where the last example
+    /// shows octal syntax.
+    ///
+    /// While supporting octal syntax isn't in and of itself a problem, it does
+    /// make good error messages harder. That is, in PCRE based regex engines,
+    /// syntax like `\0` invokes a backreference, which is explicitly
+    /// unsupported in Rust's regex engine. However, many users expect it to
+    /// be supported. Therefore, when octal support is disabled, the error
+    /// message will explicitly mention that backreferences aren't supported.
+    ///
+    /// Octal syntax is disabled by default.
+    pub fn octal(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.octal = yes;
+        self
+    }
+
+    /// Enable verbose mode in the regular expression.
+    ///
+    /// When enabled, verbose mode permits insigificant whitespace in many
+    /// places in the regular expression, as well as comments. Comments are
+    /// started using `#` and continue until the end of the line.
+    ///
+    /// By default, this is disabled. It may be selectively enabled in the
+    /// regular expression by using the `x` flag regardless of this setting.
+    pub fn ignore_whitespace(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.ignore_whitespace = yes;
+        self
+    }
+}
+
+/// A regular expression parser.
+///
+/// This parses a string representation of a regular expression into an
+/// abstract syntax tree. The size of the tree is proportional to the length
+/// of the regular expression pattern.
+///
+/// A `Parser` can be configured in more detail via a
+/// [`ParserBuilder`](struct.ParserBuilder.html).
+#[derive(Clone, Debug)]
+pub struct Parser {
+    /// The current position of the parser.
+    pos: Cell<Position>,
+    /// The current capture index.
+    capture_index: Cell<u32>,
+    /// The maximum number of open parens/brackets allowed. If the parser
+    /// exceeds this number, then an error is returned.
+    nest_limit: u32,
+    /// Whether to support octal syntax or not. When `false`, the parser will
+    /// return an error helpfully pointing out that backreferences are not
+    /// supported.
+    octal: bool,
+    /// The initial setting for `ignore_whitespace` as provided by
+    /// Th`ParserBuilder`. is is used when reseting the parser's state.
+    initial_ignore_whitespace: bool,
+    /// Whether whitespace should be ignored. When enabled, comments are
+    /// also permitted.
+    ignore_whitespace: Cell<bool>,
+    /// A list of comments, in order of appearance.
+    comments: RefCell<Vec<ast::Comment>>,
+    /// A stack of grouped sub-expressions, including alternations.
+    stack_group: RefCell<Vec<GroupState>>,
+    /// A stack of nested character classes. This is only non-empty when
+    /// parsing a class.
+    stack_class: RefCell<Vec<ClassState>>,
+    /// A sorted sequence of capture names. This is used to detect duplicate
+    /// capture names and report an error if one is detected.
+    capture_names: RefCell<Vec<ast::CaptureName>>,
+    /// A scratch buffer used in various places. Mostly this is used to
+    /// accumulate relevant characters from parts of a pattern.
+    scratch: RefCell<String>,
+}
+
+/// ParserI is the internal parser implementation.
+///
+/// We use this separate type so that we can carry the provided pattern string
+/// along with us. In particular, a `Parser` internal state is not tied to any
+/// one pattern, but `ParserI` is.
+///
+/// This type also lets us use `ParserI<&Parser>` in production code while
+/// retaining the convenience of `ParserI<Parser>` for tests, which sometimes
+/// work against the internal interface of the parser.
+#[derive(Clone, Debug)]
+struct ParserI<'s, P> {
+    /// The parser state/configuration.
+    parser: P,
+    /// The full regular expression provided by the user.
+    pattern: &'s str,
+}
+
+/// GroupState represents a single stack frame while parsing nested groups
+/// and alternations. Each frame records the state up to an opening parenthesis
+/// or a alternating bracket `|`.
+#[derive(Clone, Debug)]
+enum GroupState {
+    /// This state is pushed whenever an opening group is found.
+    Group {
+        /// The concatenation immediately preceding the opening group.
+        concat: ast::Concat,
+        /// The group that has been opened. Its sub-AST is always empty.
+        group: ast::Group,
+        /// Whether this group has the `x` flag enabled or not.
+        ignore_whitespace: bool,
+    },
+    /// This state is pushed whenever a new alternation branch is found. If
+    /// an alternation branch is found and this state is at the top of the
+    /// stack, then this state should be modified to include the new
+    /// alternation.
+    Alternation(ast::Alternation),
+}
+
+/// ClassState represents a single stack frame while parsing character classes.
+/// Each frame records the state up to an intersection, difference, symmetric
+/// difference or nested class.
+///
+/// Note that a parser's character class stack is only non-empty when parsing
+/// a character class. In all other cases, it is empty.
+#[derive(Clone, Debug)]
+enum ClassState {
+    /// This state is pushed whenever an opening bracket is found.
+    Open {
+        /// The union of class items immediately preceding this class.
+        union: ast::ClassSetUnion,
+        /// The class that has been opened. Typically this just corresponds
+        /// to the `[`, but it can also include `[^` since `^` indicates
+        /// negation of the class.
+        set: ast::ClassBracketed,
+    },
+    /// This state is pushed when a operator is seen. When popped, the stored
+    /// set becomes the left hand side of the operator.
+    Op {
+        /// The type of the operation, i.e., &&, -- or ~~.
+        kind: ast::ClassSetBinaryOpKind,
+        /// The left-hand side of the operator.
+        lhs: ast::ClassSet,
+    },
+}
+
+impl Parser {
+    /// Create a new parser with a default configuration.
+    ///
+    /// The parser can be run with either the `parse` or `parse_with_comments`
+    /// methods. The parse methods return an abstract syntax tree.
+    ///
+    /// To set configuration options on the parser, use
+    /// [`ParserBuilder`](struct.ParserBuilder.html).
+    pub fn new() -> Parser {
+        ParserBuilder::new().build()
+    }
+
+    /// Parse the regular expression into an abstract syntax tree.
+    pub fn parse(&mut self, pattern: &str) -> Result<Ast> {
+        ParserI::new(self, pattern).parse()
+    }
+
+    /// Parse the regular expression and return an abstract syntax tree with
+    /// all of the comments found in the pattern.
+    pub fn parse_with_comments(
+        &mut self,
+        pattern: &str,
+    ) -> Result<ast::WithComments> {
+        ParserI::new(self, pattern).parse_with_comments()
+    }
+
+    /// Reset the internal state of a parser.
+    ///
+    /// This is called at the beginning of every parse. This prevents the
+    /// parser from running with inconsistent state (say, if a previous
+    /// invocation returned an error and the parser is reused).
+    fn reset(&self) {
+        // These settings should be in line with the construction
+        // in `ParserBuilder::build`.
+        self.pos.set(Position { offset: 0, line: 1, column: 1});
+        self.ignore_whitespace.set(self.initial_ignore_whitespace);
+        self.comments.borrow_mut().clear();
+        self.stack_group.borrow_mut().clear();
+        self.stack_class.borrow_mut().clear();
+    }
+}
+
+impl<'s, P: Borrow<Parser>> ParserI<'s, P> {
+    /// Build an internal parser from a parser configuration and a pattern.
+    fn new(parser: P, pattern: &'s str) -> ParserI<'s, P> {
+        ParserI { parser: parser, pattern: pattern }
+    }
+
+    /// Return a reference to the parser state.
+    fn parser(&self) -> &Parser {
+        self.parser.borrow()
+    }
+
+    /// Return a reference to the pattern being parsed.
+    fn pattern(&self) -> &str {
+        self.pattern.borrow()
+    }
+
+    /// Create a new error with the given span and error type.
+    fn error(&self, span: Span, kind: ast::ErrorKind) -> ast::Error {
+        ast::Error {
+            kind: kind,
+            pattern: self.pattern().to_string(),
+            span: span,
+        }
+    }
+
+    /// Return the current offset of the parser.
+    ///
+    /// The offset starts at `0` from the beginning of the regular expression
+    /// pattern string.
+    fn offset(&self) -> usize {
+        self.parser().pos.get().offset
+    }
+
+    /// Return the current line number of the parser.
+    ///
+    /// The line number starts at `1`.
+    fn line(&self) -> usize {
+        self.parser().pos.get().line
+    }
+
+    /// Return the current column of the parser.
+    ///
+    /// The column number starts at `1` and is reset whenever a `\n` is seen.
+    fn column(&self) -> usize {
+        self.parser().pos.get().column
+    }
+
+    /// Return the next capturing index. Each subsequent call increments the
+    /// internal index.
+    ///
+    /// The span given should correspond to the location of the opening
+    /// parenthesis.
+    ///
+    /// If the capture limit is exceeded, then an error is returned.
+    fn next_capture_index(&self, span: Span) -> Result<u32> {
+        let current = self.parser().capture_index.get();
+        let i = current.checked_add(1).ok_or_else(|| {
+            self.error(span, ast::ErrorKind::CaptureLimitExceeded)
+        })?;
+        self.parser().capture_index.set(i);
+        Ok(i)
+    }
+
+    /// Adds the given capture name to this parser. If this capture name has
+    /// already been used, then an error is returned.
+    fn add_capture_name(&self, cap: &ast::CaptureName) -> Result<()> {
+        let mut names = self.parser().capture_names.borrow_mut();
+        match names.binary_search_by_key(
+            &cap.name.as_str(),
+            |c| c.name.as_str(),
+        ) {
+            Err(i) => {
+                names.insert(i, cap.clone());
+                Ok(())
+            }
+            Ok(i) => {
+                Err(self.error(cap.span, ast::ErrorKind::GroupNameDuplicate {
+                    original: names[i].span,
+                }))
+            }
+        }
+    }
+
+    /// Return whether the parser should ignore whitespace or not.
+    fn ignore_whitespace(&self) -> bool {
+        self.parser().ignore_whitespace.get()
+    }
+
+    /// Return the character at the current position of the parser.
+    ///
+    /// This panics if the current position does not point to a valid char.
+    fn char(&self) -> char {
+        self.char_at(self.offset())
+    }
+
+    /// Return the character at the given position.
+    ///
+    /// This panics if the given position does not point to a valid char.
+    fn char_at(&self, i: usize) -> char {
+        self.pattern()[i..].chars().next()
+            .unwrap_or_else(|| {
+                panic!("expected char at offset {}", i)
+            })
+    }
+
+    /// Bump the parser to the next Unicode scalar value.
+    ///
+    /// If the end of the input has been reached, then `false` is returned.
+    fn bump(&self) -> bool {
+        if self.is_eof() {
+            return false;
+        }
+        let Position { mut offset, mut line, mut column } = self.pos();
+        if self.char() == '\n' {
+            line = line.checked_add(1).unwrap();
+            column = 1;
+        } else {
+            column = column.checked_add(1).unwrap();
+        }
+        offset += self.char().len_utf8();
+        self.parser().pos.set(Position {
+            offset: offset,
+            line: line,
+            column: column,
+        });
+        self.pattern()[self.offset()..].chars().next().is_some()
+    }
+
+    /// If the substring starting at the current position of the parser has
+    /// the given prefix, then bump the parser to the character immediately
+    /// following the prefix and return true. Otherwise, don't bump the parser
+    /// and return false.
+    fn bump_if(&self, prefix: &str) -> bool {
+        if self.pattern()[self.offset()..].starts_with(prefix) {
+            for _ in 0..prefix.chars().count() {
+                self.bump();
+            }
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Returns true if and only if the parser is positioned at a look-around
+    /// prefix. The conditions under which this returns true must always
+    /// correspond to a regular expression that would otherwise be consider
+    /// invalid.
+    ///
+    /// This should only be called immediately after parsing the opening of
+    /// a group or a set of flags.
+    fn is_lookaround_prefix(&self) -> bool {
+        self.bump_if("?=")
+        || self.bump_if("?!")
+        || self.bump_if("?<=")
+        || self.bump_if("?<!")
+    }
+
+    /// Bump the parser, and if the `x` flag is enabled, bump through any
+    /// subsequent spaces. Return true if and only if the parser is not at
+    /// EOF.
+    fn bump_and_bump_space(&self) -> bool {
+        if !self.bump() {
+            return false;
+        }
+        self.bump_space();
+        !self.is_eof()
+    }
+
+    /// If the `x` flag is enabled (i.e., whitespace insensitivity with
+    /// comments), then this will advance the parser through all whitespace
+    /// and comments to the next non-whitespace non-comment byte.
+    ///
+    /// If the `x` flag is disabled, then this is a no-op.
+    ///
+    /// This should be used selectively throughout the parser where
+    /// arbitrary whitespace is permitted when the `x` flag is enabled. For
+    /// example, `{   5  , 6}` is equivalent to `{5,6}`.
+    fn bump_space(&self) {
+        if !self.ignore_whitespace() {
+            return;
+        }
+        while !self.is_eof() {
+            if self.char().is_whitespace() {
+                self.bump();
+            } else if self.char() == '#' {
+                let start = self.pos();
+                let mut comment_text = String::new();
+                self.bump();
+                while !self.is_eof() {
+                    let c = self.char();
+                    self.bump();
+                    if c == '\n' {
+                        break;
+                    }
+                    comment_text.push(c);
+                }
+                let comment = ast::Comment {
+                    span: Span::new(start, self.pos()),
+                    comment: comment_text,
+                };
+                self.parser().comments.borrow_mut().push(comment);
+            } else {
+                break;
+            }
+        }
+    }
+
+    /// Peek at the next character in the input without advancing the parser.
+    ///
+    /// If the input has been exhausted, then this returns `None`.
+    fn peek(&self) -> Option<char> {
+        if self.is_eof() {
+            return None;
+        }
+        self.pattern()[self.offset() + self.char().len_utf8()..].chars().next()
+    }
+
+    /// Like peek, but will ignore spaces when the parser is in whitespace
+    /// insensitive mode.
+    fn peek_space(&self) -> Option<char> {
+        if !self.ignore_whitespace() {
+            return self.peek();
+        }
+        if self.is_eof() {
+            return None;
+        }
+        let mut start = self.offset() + self.char().len_utf8();
+        let mut in_comment = false;
+        for (i, c) in self.pattern()[start..].char_indices() {
+            if c.is_whitespace() {
+                continue;
+            } else if !in_comment && c == '#' {
+                in_comment = true;
+            } else if in_comment && c == '\n' {
+                in_comment = false;
+            } else {
+                start += i;
+                break;
+            }
+        }
+        self.pattern()[start..].chars().next()
+    }
+
+    /// Returns true if the next call to `bump` would return false.
+    fn is_eof(&self) -> bool {
+        self.offset() == self.pattern().len()
+    }
+
+    /// Return the current position of the parser, which includes the offset,
+    /// line and column.
+    fn pos(&self) -> Position {
+        self.parser().pos.get()
+    }
+
+    /// Create a span at the current position of the parser. Both the start
+    /// and end of the span are set.
+    fn span(&self) -> Span {
+        Span::splat(self.pos())
+    }
+
+    /// Create a span that covers the current character.
+    fn span_char(&self) -> Span {
+        let mut next = Position {
+            offset: self.offset().checked_add(self.char().len_utf8()).unwrap(),
+            line: self.line(),
+            column: self.column().checked_add(1).unwrap(),
+        };
+        if self.char() == '\n' {
+            next.line += 1;
+            next.column = 1;
+        }
+        Span::new(self.pos(), next)
+    }
+
+    /// Parse and push a single alternation on to the parser's internal stack.
+    /// If the top of the stack already has an alternation, then add to that
+    /// instead of pushing a new one.
+    ///
+    /// The concatenation given corresponds to a single alternation branch.
+    /// The concatenation returned starts the next branch and is empty.
+    ///
+    /// This assumes the parser is currently positioned at `|` and will advance
+    /// the parser to the character following `|`.
+    fn push_alternate(&self, mut concat: ast::Concat) -> Result<ast::Concat> {
+        assert_eq!(self.char(), '|');
+        concat.span.end = self.pos();
+        self.push_or_add_alternation(concat);
+        self.bump();
+        Ok(ast::Concat {
+            span: self.span(),
+            asts: vec![],
+        })
+    }
+
+    /// Pushes or adds the given branch of an alternation to the parser's
+    /// internal stack of state.
+    fn push_or_add_alternation(&self, concat: ast::Concat) {
+        use self::GroupState::*;
+
+        let mut stack = self.parser().stack_group.borrow_mut();
+        if let Some(&mut Alternation(ref mut alts)) = stack.last_mut() {
+            alts.asts.push(concat.into_ast());
+            return;
+        }
+        stack.push(Alternation(ast::Alternation {
+            span: Span::new(concat.span.start, self.pos()),
+            asts: vec![concat.into_ast()],
+        }));
+    }
+
+    /// Parse and push a group AST (and its parent concatenation) on to the
+    /// parser's internal stack. Return a fresh concatenation corresponding
+    /// to the group's sub-AST.
+    ///
+    /// If a set of flags was found (with no group), then the concatenation
+    /// is returned with that set of flags added.
+    ///
+    /// This assumes that the parser is currently positioned on the opening
+    /// parenthesis. It advances the parser to the character at the start
+    /// of the sub-expression (or adjoining expression).
+    ///
+    /// If there was a problem parsing the start of the group, then an error
+    /// is returned.
+    fn push_group(&self, mut concat: ast::Concat) -> Result<ast::Concat> {
+        assert_eq!(self.char(), '(');
+        match self.parse_group()? {
+            Either::Left(set) => {
+                let ignore = set.flags.flag_state(ast::Flag::IgnoreWhitespace);
+                if let Some(v) = ignore {
+                    self.parser().ignore_whitespace.set(v);
+                }
+
+                concat.asts.push(Ast::Flags(set));
+                Ok(concat)
+            }
+            Either::Right(group) => {
+                let old_ignore_whitespace = self.ignore_whitespace();
+                let new_ignore_whitespace = group
+                    .flags()
+                    .and_then(|f| f.flag_state(ast::Flag::IgnoreWhitespace))
+                    .unwrap_or(old_ignore_whitespace);
+                self.parser().stack_group.borrow_mut().push(GroupState::Group {
+                    concat: concat,
+                    group: group,
+                    ignore_whitespace: old_ignore_whitespace,
+                });
+                self.parser().ignore_whitespace.set(new_ignore_whitespace);
+                Ok(ast::Concat {
+                    span: self.span(),
+                    asts: vec![],
+                })
+            }
+        }
+    }
+
+    /// Pop a group AST from the parser's internal stack and set the group's
+    /// AST to the given concatenation. Return the concatenation containing
+    /// the group.
+    ///
+    /// This assumes that the parser is currently positioned on the closing
+    /// parenthesis and advances the parser to the character following the `)`.
+    ///
+    /// If no such group could be popped, then an unopened group error is
+    /// returned.
+    fn pop_group(&self, mut group_concat: ast::Concat) -> Result<ast::Concat> {
+        use self::GroupState::*;
+
+        assert_eq!(self.char(), ')');
+        let mut stack = self.parser().stack_group.borrow_mut();
+        let (mut prior_concat, mut group, ignore_whitespace, alt) =
+            match stack.pop() {
+                Some(Group { concat, group, ignore_whitespace }) => {
+                    (concat, group, ignore_whitespace, None)
+                }
+                Some(Alternation(alt)) => {
+                    match stack.pop() {
+                        Some(Group { concat, group, ignore_whitespace }) => {
+                            (concat, group, ignore_whitespace, Some(alt))
+                        }
+                        None | Some(Alternation(_)) => {
+                            return Err(self.error(
+                                self.span_char(),
+                                ast::ErrorKind::GroupUnopened,
+                            ));
+                        }
+                    }
+                }
+                None => {
+                    return Err(self.error(
+                        self.span_char(),
+                        ast::ErrorKind::GroupUnopened,
+                    ));
+                }
+            };
+        self.parser().ignore_whitespace.set(ignore_whitespace);
+        group_concat.span.end = self.pos();
+        self.bump();
+        group.span.end = self.pos();
+        match alt {
+            Some(mut alt) => {
+                alt.span.end = group_concat.span.end;
+                alt.asts.push(group_concat.into_ast());
+                group.ast = Box::new(alt.into_ast());
+            }
+            None => {
+                group.ast = Box::new(group_concat.into_ast());
+            }
+        }
+        prior_concat.asts.push(Ast::Group(group));
+        Ok(prior_concat)
+    }
+
+    /// Pop the last state from the parser's internal stack, if it exists, and
+    /// add the given concatenation to it. There either must be no state or a
+    /// single alternation item on the stack. Any other scenario produces an
+    /// error.
+    ///
+    /// This assumes that the parser has advanced to the end.
+    fn pop_group_end(&self, mut concat: ast::Concat) -> Result<Ast> {
+        concat.span.end = self.pos();
+        let mut stack = self.parser().stack_group.borrow_mut();
+        let ast = match stack.pop() {
+            None => Ok(concat.into_ast()),
+            Some(GroupState::Alternation(mut alt)) => {
+                alt.span.end = self.pos();
+                alt.asts.push(concat.into_ast());
+                Ok(Ast::Alternation(alt))
+            }
+            Some(GroupState::Group { group, .. }) => {
+                return Err(self.error(
+                    group.span,
+                    ast::ErrorKind::GroupUnclosed,
+                ));
+            }
+        };
+        // If we try to pop again, there should be nothing.
+        match stack.pop() {
+            None => ast,
+            Some(GroupState::Alternation(_)) => {
+                // This unreachable is unfortunate. This case can't happen
+                // because the only way we can be here is if there were two
+                // `GroupState::Alternation`s adjacent in the parser's stack,
+                // which we guarantee to never happen because we never push a
+                // `GroupState::Alternation` if one is already at the top of
+                // the stack.
+                unreachable!()
+            }
+            Some(GroupState::Group { group, .. }) => {
+                Err(self.error(group.span, ast::ErrorKind::GroupUnclosed))
+            }
+        }
+    }
+
+    /// Parse the opening of a character class and push the current class
+    /// parsing context onto the parser's stack. This assumes that the parser
+    /// is positioned at an opening `[`. The given union should correspond to
+    /// the union of set items built up before seeing the `[`.
+    ///
+    /// If there was a problem parsing the opening of the class, then an error
+    /// is returned. Otherwise, a new union of set items for the class is
+    /// returned (which may be populated with either a `]` or a `-`).
+    fn push_class_open(
+        &self,
+        parent_union: ast::ClassSetUnion,
+    ) -> Result<ast::ClassSetUnion> {
+        assert_eq!(self.char(), '[');
+
+        let (nested_set, nested_union) = self.parse_set_class_open()?;
+        self.parser().stack_class.borrow_mut().push(ClassState::Open {
+            union: parent_union,
+            set: nested_set,
+        });
+        Ok(nested_union)
+    }
+
+    /// Parse the end of a character class set and pop the character class
+    /// parser stack. The union given corresponds to the last union built
+    /// before seeing the closing `]`. The union returned corresponds to the
+    /// parent character class set with the nested class added to it.
+    ///
+    /// This assumes that the parser is positioned at a `]` and will advance
+    /// the parser to the byte immediately following the `]`.
+    ///
+    /// If the stack is empty after popping, then this returns the final
+    /// "top-level" character class AST (where a "top-level" character class
+    /// is one that is not nested inside any other character class).
+    ///
+    /// If there is no corresponding opening bracket on the parser's stack,
+    /// then an error is returned.
+    fn pop_class(
+        &self,
+        nested_union: ast::ClassSetUnion,
+    ) -> Result<Either<ast::ClassSetUnion, ast::Class>> {
+        assert_eq!(self.char(), ']');
+
+        let item = ast::ClassSet::Item(nested_union.into_item());
+        let prevset = self.pop_class_op(item);
+        let mut stack = self.parser().stack_class.borrow_mut();
+        match stack.pop() {
+            None => {
+                // We can never observe an empty stack:
+                //
+                // 1) We are guaranteed to start with a non-empty stack since
+                //    the character class parser is only initiated when it sees
+                //    a `[`.
+                // 2) If we ever observe an empty stack while popping after
+                //    seeing a `]`, then we signal the character class parser
+                //    to terminate.
+                panic!("unexpected empty character class stack")
+            },
+            Some(ClassState::Op { .. }) => {
+                // This panic is unfortunate, but this case is impossible
+                // since we already popped the Op state if one exists above.
+                // Namely, every push to the class parser stack is guarded by
+                // whether an existing Op is already on the top of the stack.
+                // If it is, the existing Op is modified. That is, the stack
+                // can never have consecutive Op states.
+                panic!("unexpected ClassState::Op")
+            }
+            Some(ClassState::Open { mut union, mut set }) => {
+                self.bump();
+                set.span.end = self.pos();
+                set.kind = prevset;
+                if stack.is_empty() {
+                    Ok(Either::Right(ast::Class::Bracketed(set)))
+                } else {
+                    union.push(ast::ClassSetItem::Bracketed(Box::new(set)));
+                    Ok(Either::Left(union))
+                }
+            }
+        }
+    }
+
+    /// Return an "unclosed class" error whose span points to the most
+    /// recently opened class.
+    ///
+    /// This should only be called while parsing a character class.
+    fn unclosed_class_error(&self) -> ast::Error {
+        for state in self.parser().stack_class.borrow().iter().rev() {
+            match *state {
+                ClassState::Open { ref set, .. } => {
+                    return self.error(set.span, ast::ErrorKind::ClassUnclosed);
+                }
+                _ => {}
+            }
+        }
+        // We are guaranteed to have a non-empty stack with at least
+        // one open bracket, so we should never get here.
+        panic!("no open character class found")
+    }
+
+    /// Push the current set of class items on to the class parser's stack as
+    /// the left hand side of the given operator.
+    ///
+    /// A fresh set union is returned, which should be used to build the right
+    /// hand side of this operator.
+    fn push_class_op(
+        &self,
+        next_kind: ast::ClassSetBinaryOpKind,
+        next_union: ast::ClassSetUnion,
+    ) -> ast::ClassSetUnion {
+
+        let item = ast::ClassSet::Item(next_union.into_item());
+        let new_lhs = self.pop_class_op(item);
+        self.parser().stack_class.borrow_mut().push(ClassState::Op {
+            kind: next_kind,
+            lhs: new_lhs,
+        });
+        ast::ClassSetUnion { span: self.span(), items: vec![] }
+    }
+
+    /// Pop a character class set from the character class parser stack. If the
+    /// top of the stack is just an item (not an operation), then return the
+    /// given set unchanged. If the top of the stack is an operation, then the
+    /// given set will be used as the rhs of the operation on the top of the
+    /// stack. In that case, the binary operation is returned as a set.
+    fn pop_class_op(&self, rhs: ast::ClassSet) -> ast::ClassSet {
+        let mut stack = self.parser().stack_class.borrow_mut();
+        let (kind, lhs) = match stack.pop() {
+            Some(ClassState::Op { kind, lhs }) => (kind, lhs),
+            Some(state @ ClassState::Open { .. }) => {
+                stack.push(state);
+                return rhs;
+            }
+            None => unreachable!(),
+        };
+        let span = Span::new(lhs.span().start, rhs.span().end);
+        ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+            span: span,
+            kind: kind,
+            lhs: Box::new(lhs),
+            rhs: Box::new(rhs),
+        })
+    }
+}
+
+impl<'s, P: Borrow<Parser>> ParserI<'s, P> {
+    /// Parse the regular expression into an abstract syntax tree.
+    fn parse(&self) -> Result<Ast> {
+        self.parse_with_comments().map(|astc| astc.ast)
+    }
+
+    /// Parse the regular expression and return an abstract syntax tree with
+    /// all of the comments found in the pattern.
+    fn parse_with_comments(&self) -> Result<ast::WithComments> {
+        assert_eq!(self.offset(), 0, "parser can only be used once");
+        self.parser().reset();
+        let mut concat = ast::Concat {
+            span: self.span(),
+            asts: vec![],
+        };
+        loop {
+            self.bump_space();
+            if self.is_eof() {
+                break;
+            }
+            match self.char() {
+                '(' => concat = self.push_group(concat)?,
+                ')' => concat = self.pop_group(concat)?,
+                '|' => concat = self.push_alternate(concat)?,
+                '[' => {
+                    let class = self.parse_set_class()?;
+                    concat.asts.push(Ast::Class(class));
+                }
+                '?' => {
+                    concat = self.parse_uncounted_repetition(
+                        concat, ast::RepetitionKind::ZeroOrOne)?;
+                }
+                '*' => {
+                    concat = self.parse_uncounted_repetition(
+                        concat, ast::RepetitionKind::ZeroOrMore)?;
+                }
+                '+' => {
+                    concat = self.parse_uncounted_repetition(
+                        concat, ast::RepetitionKind::OneOrMore)?;
+                }
+                '{' => {
+                    concat = self.parse_counted_repetition(concat)?;
+                }
+                _ => concat.asts.push(self.parse_primitive()?.into_ast()),
+            }
+        }
+        let ast = self.pop_group_end(concat)?;
+        NestLimiter::new(self).check(&ast)?;
+        Ok(ast::WithComments {
+            ast: ast,
+            comments: mem::replace(
+                &mut *self.parser().comments.borrow_mut(),
+                vec![],
+            ),
+        })
+    }
+
+    /// Parses an uncounted repetition operation. An uncounted repetition
+    /// operator includes ?, * and +, but does not include the {m,n} syntax.
+    /// The given `kind` should correspond to the operator observed by the
+    /// caller.
+    ///
+    /// This assumes that the paser is currently positioned at the repetition
+    /// operator and advances the parser to the first character after the
+    /// operator. (Note that the operator may include a single additional `?`,
+    /// which makes the operator ungreedy.)
+    ///
+    /// The caller should include the concatenation that is being built. The
+    /// concatenation returned includes the repetition operator applied to the
+    /// last expression in the given concatenation.
+    fn parse_uncounted_repetition(
+        &self,
+        mut concat: ast::Concat,
+        kind: ast::RepetitionKind,
+    ) -> Result<ast::Concat> {
+        assert!(
+            self.char() == '?' || self.char() == '*' || self.char() == '+');
+        let op_start = self.pos();
+        let ast = match concat.asts.pop() {
+            Some(ast) => ast,
+            None => return Err(self.error(
+                self.span(),
+                ast::ErrorKind::RepetitionMissing,
+            )),
+        };
+        match ast {
+            Ast::Empty(_) | Ast::Flags(_) => return Err(self.error(
+                self.span(),
+                ast::ErrorKind::RepetitionMissing,
+            )),
+            _ => {}
+        }
+        let mut greedy = true;
+        if self.bump() && self.char() == '?' {
+            greedy = false;
+            self.bump();
+        }
+        concat.asts.push(Ast::Repetition(ast::Repetition {
+            span: ast.span().with_end(self.pos()),
+            op: ast::RepetitionOp {
+                span: Span::new(op_start, self.pos()),
+                kind: kind,
+            },
+            greedy: greedy,
+            ast: Box::new(ast),
+        }));
+        Ok(concat)
+    }
+
+    /// Parses a counted repetition operation. A counted repetition operator
+    /// corresponds to the {m,n} syntax, and does not include the ?, * or +
+    /// operators.
+    ///
+    /// This assumes that the paser is currently positioned at the opening `{`
+    /// and advances the parser to the first character after the operator.
+    /// (Note that the operator may include a single additional `?`, which
+    /// makes the operator ungreedy.)
+    ///
+    /// The caller should include the concatenation that is being built. The
+    /// concatenation returned includes the repetition operator applied to the
+    /// last expression in the given concatenation.
+    fn parse_counted_repetition(
+        &self,
+        mut concat: ast::Concat,
+    ) -> Result<ast::Concat> {
+        assert!(self.char() == '{');
+        let start = self.pos();
+        let ast = match concat.asts.pop() {
+            Some(ast) => ast,
+            None => return Err(self.error(
+                self.span(),
+                ast::ErrorKind::RepetitionMissing,
+            )),
+        };
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::RepetitionCountUnclosed,
+            ));
+        }
+        let count_start = self.parse_decimal()?;
+        let mut range = ast::RepetitionRange::Exactly(count_start);
+        if self.is_eof() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::RepetitionCountUnclosed,
+            ));
+        }
+        if self.char() == ',' {
+            if !self.bump_and_bump_space() {
+                return Err(self.error(
+                    Span::new(start, self.pos()),
+                    ast::ErrorKind::RepetitionCountUnclosed,
+                ));
+            }
+            if self.char() != '}' {
+                let count_end = self.parse_decimal()?;
+                range = ast::RepetitionRange::Bounded(count_start, count_end);
+            } else {
+                range = ast::RepetitionRange::AtLeast(count_start);
+            }
+        }
+        if self.is_eof() || self.char() != '}' {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::RepetitionCountUnclosed,
+            ));
+        }
+
+        let mut greedy = true;
+        if self.bump_and_bump_space() && self.char() == '?' {
+            greedy = false;
+            self.bump();
+        }
+
+        let op_span = Span::new(start, self.pos());
+        if !range.is_valid() {
+            return Err(self.error(
+                op_span,
+                ast::ErrorKind::RepetitionCountInvalid,
+            ));
+        }
+        concat.asts.push(Ast::Repetition(ast::Repetition {
+            span: ast.span().with_end(self.pos()),
+            op: ast::RepetitionOp {
+                span: op_span,
+                kind: ast::RepetitionKind::Range(range),
+            },
+            greedy: greedy,
+            ast: Box::new(ast),
+        }));
+        Ok(concat)
+    }
+
+    /// Parse a group (which contains a sub-expression) or a set of flags.
+    ///
+    /// If a group was found, then it is returned with an empty AST. If a set
+    /// of flags is found, then that set is returned.
+    ///
+    /// The parser should be positioned at the opening parenthesis.
+    ///
+    /// This advances the parser to the character before the start of the
+    /// sub-expression (in the case of a group) or to the closing parenthesis
+    /// immediately following the set of flags.
+    ///
+    /// # Errors
+    ///
+    /// If flags are given and incorrectly specified, then a corresponding
+    /// error is returned.
+    ///
+    /// If a capture name is given and it is incorrectly specified, then a
+    /// corresponding error is returned.
+    fn parse_group(&self) -> Result<Either<ast::SetFlags, ast::Group>> {
+        assert_eq!(self.char(), '(');
+        let open_span = self.span_char();
+        self.bump();
+        self.bump_space();
+        if self.is_lookaround_prefix() {
+            return Err(self.error(
+                Span::new(open_span.start, self.span().end),
+                ast::ErrorKind::UnsupportedLookAround,
+            ));
+        }
+        let inner_span = self.span();
+        if self.bump_if("?P<") {
+            let capture_index = self.next_capture_index(open_span)?;
+            let cap = self.parse_capture_name(capture_index)?;
+            Ok(Either::Right(ast::Group {
+                span: open_span,
+                kind: ast::GroupKind::CaptureName(cap),
+                ast: Box::new(Ast::Empty(self.span())),
+            }))
+        } else if self.bump_if("?") {
+            if self.is_eof() {
+                return Err(self.error(
+                    open_span,
+                    ast::ErrorKind::GroupUnclosed,
+                ));
+            }
+            let flags = self.parse_flags()?;
+            let char_end = self.char();
+            self.bump();
+            if char_end == ')' {
+                // We don't allow empty flags, e.g., `(?)`. We instead
+                // interpret it as a repetition operator missing its argument.
+                if flags.items.is_empty() {
+                    return Err(self.error(
+                        inner_span,
+                        ast::ErrorKind::RepetitionMissing,
+                    ));
+                }
+                Ok(Either::Left(ast::SetFlags {
+                    span: Span { end: self.pos(), ..open_span },
+                    flags: flags,
+                }))
+            } else {
+                assert_eq!(char_end, ':');
+                Ok(Either::Right(ast::Group {
+                    span: open_span,
+                    kind: ast::GroupKind::NonCapturing(flags),
+                    ast: Box::new(Ast::Empty(self.span())),
+                }))
+            }
+        } else {
+            let capture_index = self.next_capture_index(open_span)?;
+            Ok(Either::Right(ast::Group {
+                span: open_span,
+                kind: ast::GroupKind::CaptureIndex(capture_index),
+                ast: Box::new(Ast::Empty(self.span())),
+            }))
+        }
+    }
+
+    /// Parses a capture group name. Assumes that the parser is positioned at
+    /// the first character in the name following the opening `<` (and may
+    /// possibly be EOF). This advances the parser to the first character
+    /// following the closing `>`.
+    ///
+    /// The caller must provide the capture index of the group for this name.
+    fn parse_capture_name(
+        &self,
+        capture_index: u32,
+    ) -> Result<ast::CaptureName> {
+        if self.is_eof() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::GroupNameUnexpectedEof,
+            ));
+        }
+        let start = self.pos();
+        loop {
+            if self.char() == '>' {
+                break;
+            }
+            if !is_capture_char(self.char(), self.pos() == start) {
+                return Err(self.error(
+                    self.span_char(),
+                    ast::ErrorKind::GroupNameInvalid,
+                ));
+            }
+            if !self.bump() {
+                break;
+            }
+        }
+        let end = self.pos();
+        if self.is_eof() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::GroupNameUnexpectedEof,
+            ));
+        }
+        assert_eq!(self.char(), '>');
+        self.bump();
+        let name = &self.pattern()[start.offset..end.offset];
+        if name.is_empty() {
+            return Err(self.error(
+                Span::new(start, start),
+                ast::ErrorKind::GroupNameEmpty,
+            ));
+        }
+        let capname = ast::CaptureName {
+            span: Span::new(start, end),
+            name: name.to_string(),
+            index: capture_index,
+        };
+        self.add_capture_name(&capname)?;
+        Ok(capname)
+    }
+
+    /// Parse a sequence of flags starting at the current character.
+    ///
+    /// This advances the parser to the character immediately following the
+    /// flags, which is guaranteed to be either `:` or `)`.
+    ///
+    /// # Errors
+    ///
+    /// If any flags are duplicated, then an error is returned.
+    ///
+    /// If the negation operator is used more than once, then an error is
+    /// returned.
+    ///
+    /// If no flags could be found or if the negation operation is not followed
+    /// by any flags, then an error is returned.
+    fn parse_flags(&self) -> Result<ast::Flags> {
+        let mut flags = ast::Flags {
+            span: self.span(),
+            items: vec![],
+        };
+        let mut last_was_negation = None;
+        while self.char() != ':' && self.char() != ')' {
+            if self.char() == '-' {
+                last_was_negation = Some(self.span_char());
+                let item = ast::FlagsItem {
+                    span: self.span_char(),
+                    kind: ast::FlagsItemKind::Negation,
+                };
+                if let Some(i) = flags.add_item(item) {
+                    return Err(self.error(
+                        self.span_char(),
+                        ast::ErrorKind::FlagRepeatedNegation {
+                            original: flags.items[i].span,
+                        },
+                    ));
+                }
+            } else {
+                last_was_negation = None;
+                let item = ast::FlagsItem {
+                    span: self.span_char(),
+                    kind: ast::FlagsItemKind::Flag(self.parse_flag()?),
+                };
+                if let Some(i) = flags.add_item(item) {
+                    return Err(self.error(
+                        self.span_char(),
+                        ast::ErrorKind::FlagDuplicate {
+                            original: flags.items[i].span,
+                        },
+                    ));
+                }
+            }
+            if !self.bump() {
+                return Err(self.error(
+                    self.span(),
+                    ast::ErrorKind::FlagUnexpectedEof,
+                ));
+            }
+        }
+        if let Some(span) = last_was_negation {
+            return Err(self.error(span, ast::ErrorKind::FlagDanglingNegation));
+        }
+        flags.span.end = self.pos();
+        Ok(flags)
+    }
+
+    /// Parse the current character as a flag. Do not advance the parser.
+    ///
+    /// # Errors
+    ///
+    /// If the flag is not recognized, then an error is returned.
+    fn parse_flag(&self) -> Result<ast::Flag> {
+        match self.char() {
+            'i' => Ok(ast::Flag::CaseInsensitive),
+            'm' => Ok(ast::Flag::MultiLine),
+            's' => Ok(ast::Flag::DotMatchesNewLine),
+            'U' => Ok(ast::Flag::SwapGreed),
+            'u' => Ok(ast::Flag::Unicode),
+            'x' => Ok(ast::Flag::IgnoreWhitespace),
+            _ => Err(self.error(
+                self.span_char(),
+                ast::ErrorKind::FlagUnrecognized,
+            )),
+        }
+    }
+
+    /// Parse a primitive AST. e.g., A literal, non-set character class or
+    /// assertion.
+    ///
+    /// This assumes that the parser expects a primitive at the current
+    /// location. i.e., All other non-primitive cases have been handled.
+    /// For example, if the parser's position is at `|`, then `|` will be
+    /// treated as a literal (e.g., inside a character class).
+    ///
+    /// This advances the parser to the first character immediately following
+    /// the primitive.
+    fn parse_primitive(&self) -> Result<Primitive> {
+        match self.char() {
+            '\\' => self.parse_escape(),
+            '.' => {
+                let ast = Primitive::Dot(self.span_char());
+                self.bump();
+                Ok(ast)
+            }
+            '^' => {
+                let ast = Primitive::Assertion(ast::Assertion {
+                    span: self.span_char(),
+                    kind: ast::AssertionKind::StartLine,
+                });
+                self.bump();
+                Ok(ast)
+            }
+            '$' => {
+                let ast = Primitive::Assertion(ast::Assertion {
+                    span: self.span_char(),
+                    kind: ast::AssertionKind::EndLine,
+                });
+                self.bump();
+                Ok(ast)
+            }
+            c => {
+                let ast = Primitive::Literal(ast::Literal {
+                    span: self.span_char(),
+                    kind: ast::LiteralKind::Verbatim,
+                    c: c,
+                });
+                self.bump();
+                Ok(ast)
+            }
+        }
+    }
+
+    /// Parse an escape sequence as a primitive AST.
+    ///
+    /// This assumes the parser is positioned at the start of the escape
+    /// sequence, i.e., `\`. It advances the parser to the first position
+    /// immediately following the escape sequence.
+    fn parse_escape(&self) -> Result<Primitive> {
+        assert_eq!(self.char(), '\\');
+        let start = self.pos();
+        if !self.bump() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        let c = self.char();
+        // Put some of the more complicated routines into helpers.
+        match c {
+            '0'...'7' => {
+                if !self.parser().octal {
+                    return Err(self.error(
+                        Span::new(start, self.span_char().end),
+                        ast::ErrorKind::UnsupportedBackreference,
+                    ));
+                }
+                let mut lit = self.parse_octal();
+                lit.span.start = start;
+                return Ok(Primitive::Literal(lit));
+            }
+            '8'...'9' if !self.parser().octal => {
+                return Err(self.error(
+                    Span::new(start, self.span_char().end),
+                    ast::ErrorKind::UnsupportedBackreference,
+                ));
+            }
+            'x' | 'u' | 'U' => {
+                let mut lit = self.parse_hex()?;
+                lit.span.start = start;
+                return Ok(Primitive::Literal(lit));
+            }
+            'p' | 'P' => {
+                let mut cls = self.parse_unicode_class()?;
+                cls.span.start = start;
+                return Ok(Primitive::Unicode(cls));
+            }
+            'd' | 's' | 'w' | 'D' | 'S' | 'W' => {
+                let mut cls = self.parse_perl_class();
+                cls.span.start = start;
+                return Ok(Primitive::Perl(cls));
+            }
+            _ => {}
+        }
+
+        // Handle all of the one letter sequences inline.
+        self.bump();
+        let span = Span::new(start, self.pos());
+        if is_meta_character(c) {
+            return Ok(Primitive::Literal(ast::Literal {
+                span: span,
+                kind: ast::LiteralKind::Punctuation,
+                c: c,
+            }));
+        }
+        let special = |kind, c| Ok(Primitive::Literal(ast::Literal {
+            span: span,
+            kind: ast::LiteralKind::Special(kind),
+            c: c,
+        }));
+        match c {
+            'a' => special(ast::SpecialLiteralKind::Bell, '\x07'),
+            'f' => special(ast::SpecialLiteralKind::FormFeed, '\x0C'),
+            't' => special(ast::SpecialLiteralKind::Tab, '\t'),
+            'n' => special(ast::SpecialLiteralKind::LineFeed, '\n'),
+            'r' => special(ast::SpecialLiteralKind::CarriageReturn, '\r'),
+            'v' => special(ast::SpecialLiteralKind::VerticalTab, '\x0B'),
+            ' ' if self.ignore_whitespace() => {
+                special(ast::SpecialLiteralKind::Space, ' ')
+            }
+            'A' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::StartText,
+            })),
+            'z' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::EndText,
+            })),
+            'b' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::WordBoundary,
+            })),
+            'B' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::NotWordBoundary,
+            })),
+            _ => Err(self.error(span, ast::ErrorKind::EscapeUnrecognized)),
+        }
+    }
+
+    /// Parse an octal representation of a Unicode codepoint up to 3 digits
+    /// long. This expects the parser to be positioned at the first octal
+    /// digit and advances the parser to the first character immediately
+    /// following the octal number. This also assumes that parsing octal
+    /// escapes is enabled.
+    ///
+    /// Assuming the preconditions are met, this routine can never fail.
+    fn parse_octal(&self) -> ast::Literal {
+        use std::char;
+        use std::u32;
+
+        assert!(self.parser().octal);
+        assert!('0' <= self.char() && self.char() <= '7');
+        let start = self.pos();
+        // Parse up to two more digits.
+        while
+            self.bump() &&
+            '0' <= self.char() && self.char() <= '7' &&
+            self.pos().offset - start.offset <= 2
+        {}
+        let end = self.pos();
+        let octal = &self.pattern()[start.offset..end.offset];
+        // Parsing the octal should never fail since the above guarantees a
+        // valid number.
+        let codepoint =
+            u32::from_str_radix(octal, 8).expect("valid octal number");
+        // The max value for 3 digit octal is 0777 = 511 and [0, 511] has no
+        // invalid Unicode scalar values.
+        let c = char::from_u32(codepoint).expect("Unicode scalar value");
+        ast::Literal {
+            span: Span::new(start, end),
+            kind: ast::LiteralKind::Octal,
+            c: c,
+        }
+    }
+
+    /// Parse a hex representation of a Unicode codepoint. This handles both
+    /// hex notations, i.e., `\xFF` and `\x{FFFF}`. This expects the parser to
+    /// be positioned at the `x`, `u` or `U` prefix. The parser is advanced to
+    /// the first character immediately following the hexadecimal literal.
+    fn parse_hex(&self) -> Result<ast::Literal> {
+        assert!(self.char() == 'x'
+                || self.char() == 'u'
+                || self.char() == 'U');
+
+        let hex_kind = match self.char() {
+            'x' => ast::HexLiteralKind::X,
+            'u' => ast::HexLiteralKind::UnicodeShort,
+            _ => ast::HexLiteralKind::UnicodeLong,
+        };
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        if self.char() == '{' {
+            self.parse_hex_brace(hex_kind)
+        } else {
+            self.parse_hex_digits(hex_kind)
+        }
+    }
+
+    /// Parse an N-digit hex representation of a Unicode codepoint. This
+    /// expects the parser to be positioned at the first digit and will advance
+    /// the parser to the first character immediately following the escape
+    /// sequence.
+    ///
+    /// The number of digits given must be 2 (for `\xNN`), 4 (for `\uNNNN`)
+    /// or 8 (for `\UNNNNNNNN`).
+    fn parse_hex_digits(
+        &self,
+        kind: ast::HexLiteralKind,
+    ) -> Result<ast::Literal> {
+        use std::char;
+        use std::u32;
+
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        let start = self.pos();
+        for i in 0..kind.digits() {
+            if i > 0 && !self.bump_and_bump_space() {
+                return Err(self.error(
+                    self.span(),
+                    ast::ErrorKind::EscapeUnexpectedEof,
+                ));
+            }
+            if !is_hex(self.char()) {
+                return Err(self.error(
+                    self.span_char(),
+                    ast::ErrorKind::EscapeHexInvalidDigit,
+                ));
+            }
+            scratch.push(self.char());
+        }
+        // The final bump just moves the parser past the literal, which may
+        // be EOF.
+        self.bump_and_bump_space();
+        let end = self.pos();
+        let hex = scratch.as_str();
+        match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
+            None => Err(self.error(
+                Span::new(start, end),
+                ast::ErrorKind::EscapeHexInvalid,
+            )),
+            Some(c) => Ok(ast::Literal {
+                span: Span::new(start, end),
+                kind: ast::LiteralKind::HexFixed(kind),
+                c: c,
+            }),
+        }
+    }
+
+    /// Parse a hex representation of any Unicode scalar value. This expects
+    /// the parser to be positioned at the opening brace `{` and will advance
+    /// the parser to the first character following the closing brace `}`.
+    fn parse_hex_brace(
+        &self,
+        kind: ast::HexLiteralKind,
+    ) -> Result<ast::Literal> {
+        use std::char;
+        use std::u32;
+
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        let brace_pos = self.pos();
+        let start = self.span_char().end;
+        while self.bump_and_bump_space() && self.char() != '}' {
+            if !is_hex(self.char()) {
+                return Err(self.error(
+                    self.span_char(),
+                    ast::ErrorKind::EscapeHexInvalidDigit,
+                ));
+            }
+            scratch.push(self.char());
+        }
+        if self.is_eof() {
+            return Err(self.error(
+                Span::new(brace_pos, self.pos()),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        let end = self.pos();
+        let hex = scratch.as_str();
+        assert_eq!(self.char(), '}');
+        self.bump_and_bump_space();
+
+        if hex.is_empty() {
+            return Err(self.error(
+                Span::new(brace_pos, self.pos()),
+                ast::ErrorKind::EscapeHexEmpty,
+            ));
+        }
+        match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
+            None => Err(self.error(
+                Span::new(start, end),
+                ast::ErrorKind::EscapeHexInvalid,
+            )),
+            Some(c) => Ok(ast::Literal {
+                span: Span::new(start, self.pos()),
+                kind: ast::LiteralKind::HexBrace(kind),
+                c: c,
+            }),
+        }
+    }
+
+    /// Parse a decimal number into a u32 while trimming leading and trailing
+    /// whitespace.
+    ///
+    /// This expects the parser to be positioned at the first position where
+    /// a decimal digit could occur. This will advance the parser to the byte
+    /// immediately following the last contiguous decimal digit.
+    ///
+    /// If no decimal digit could be found or if there was a problem parsing
+    /// the complete set of digits into a u32, then an error is returned.
+    fn parse_decimal(&self) -> Result<u32> {
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        while !self.is_eof() && self.char().is_whitespace() {
+            self.bump();
+        }
+        let start = self.pos();
+        while !self.is_eof() && '0' <= self.char() && self.char() <= '9' {
+            scratch.push(self.char());
+            self.bump_and_bump_space();
+        }
+        let span = Span::new(start, self.pos());
+        while !self.is_eof() && self.char().is_whitespace() {
+            self.bump_and_bump_space();
+        }
+        let digits = scratch.as_str();
+        if digits.is_empty() {
+            return Err(self.error(span, ast::ErrorKind::DecimalEmpty));
+        }
+        match u32::from_str_radix(digits, 10).ok() {
+            Some(n) => Ok(n),
+            None => Err(self.error(span, ast::ErrorKind::DecimalInvalid)),
+        }
+    }
+
+    /// Parse a standard character class consisting primarily of characters or
+    /// character ranges, but can also contain nested character classes of
+    /// any type (sans `.`).
+    ///
+    /// This assumes the parser is positioned at the opening `[`. If parsing
+    /// is successful, then the parser is advanced to the position immediately
+    /// following the closing `]`.
+    fn parse_set_class(&self) -> Result<ast::Class> {
+        assert_eq!(self.char(), '[');
+
+        let mut union = ast::ClassSetUnion {
+            span: self.span(),
+            items: vec![],
+        };
+        loop {
+            self.bump_space();
+            if self.is_eof() {
+                return Err(self.unclosed_class_error());
+            }
+            match self.char() {
+                '[' => {
+                    // If we've already parsed the opening bracket, then
+                    // attempt to treat this as the beginning of an ASCII
+                    // class. If ASCII class parsing fails, then the parser
+                    // backs up to `[`.
+                    if !self.parser().stack_class.borrow().is_empty() {
+                        if let Some(cls) = self.maybe_parse_ascii_class() {
+                            union.push(ast::ClassSetItem::Ascii(cls));
+                            continue;
+                        }
+                    }
+                    union = self.push_class_open(union)?;
+                }
+                ']' => {
+                    match self.pop_class(union)? {
+                        Either::Left(nested_union) => { union = nested_union; }
+                        Either::Right(class) => return Ok(class),
+                    }
+                }
+                '&' if self.peek() == Some('&') => {
+                    assert!(self.bump_if("&&"));
+                    union = self.push_class_op(
+                        ast::ClassSetBinaryOpKind::Intersection, union);
+                }
+                '-' if self.peek() == Some('-') => {
+                    assert!(self.bump_if("--"));
+                    union = self.push_class_op(
+                        ast::ClassSetBinaryOpKind::Difference, union);
+                }
+                '~' if self.peek() == Some('~') => {
+                    assert!(self.bump_if("~~"));
+                    union = self.push_class_op(
+                        ast::ClassSetBinaryOpKind::SymmetricDifference, union);
+                }
+                _ => {
+                    union.push(self.parse_set_class_range()?);
+                }
+            }
+        }
+    }
+
+    /// Parse a single primitive item in a character class set. The item to
+    /// be parsed can either be one of a simple literal character, a range
+    /// between two simple literal characters or a "primitive" character
+    /// class like \w or \p{Greek}.
+    ///
+    /// If an invalid escape is found, or if a character class is found where
+    /// a simple literal is expected (e.g., in a range), then an error is
+    /// returned.
+    fn parse_set_class_range(&self) -> Result<ast::ClassSetItem> {
+        let prim1 = self.parse_set_class_item()?;
+        self.bump_space();
+        if self.is_eof() {
+            return Err(self.unclosed_class_error());
+        }
+        // If the next char isn't a `-`, then we don't have a range.
+        // There are two exceptions. If the char after a `-` is a `]`, then
+        // `-` is interpreted as a literal `-`. Alternatively, if the char
+        // after a `-` is a `-`, then `--` corresponds to a "difference"
+        // operation.
+        if self.char() != '-'
+            || self.peek_space() == Some(']')
+            || self.peek_space() == Some('-')
+        {
+            return prim1.into_class_set_item(self);
+        }
+        // OK, now we're parsing a range, so bump past the `-` and parse the
+        // second half of the range.
+        if !self.bump_and_bump_space() {
+            return Err(self.unclosed_class_error());
+        }
+        let prim2 = self.parse_set_class_item()?;
+        let range = ast::ClassSetRange {
+            span: Span::new(prim1.span().start, prim2.span().end),
+            start: prim1.into_class_literal(self)?,
+            end: prim2.into_class_literal(self)?,
+        };
+        if !range.is_valid() {
+            return Err(self.error(
+                range.span,
+                ast::ErrorKind::ClassRangeInvalid,
+            ));
+        }
+        Ok(ast::ClassSetItem::Range(range))
+    }
+
+    /// Parse a single item in a character class as a primitive, where the
+    /// primitive either consists of a verbatim literal or a single escape
+    /// sequence.
+    ///
+    /// This assumes the parser is positioned at the beginning of a primitive,
+    /// and advances the parser to the first position after the primitive if
+    /// successful.
+    ///
+    /// Note that it is the caller's responsibility to report an error if an
+    /// illegal primitive was parsed.
+    fn parse_set_class_item(&self) -> Result<Primitive> {
+        if self.char() == '\\' {
+            self.parse_escape()
+        } else {
+            let x = Primitive::Literal(ast::Literal {
+                span: self.span_char(),
+                kind: ast::LiteralKind::Verbatim,
+                c: self.char(),
+            });
+            self.bump();
+            Ok(x)
+        }
+    }
+
+    /// Parses the opening of a character class set. This includes the opening
+    /// bracket along with `^` if present to indicate negation. This also
+    /// starts parsing the opening set of unioned items if applicable, since
+    /// there are special rules applied to certain characters in the opening
+    /// of a character class. For example, `[^]]` is the class of all
+    /// characters not equal to `]`. (`]` would need to be escaped in any other
+    /// position.) Similarly for `-`.
+    ///
+    /// In all cases, the op inside the returned `ast::ClassBracketed` is an
+    /// empty union. This empty union should be replaced with the actual item
+    /// when it is popped from the parser's stack.
+    ///
+    /// This assumes the parser is positioned at the opening `[` and advances
+    /// the parser to the first non-special byte of the character class.
+    ///
+    /// An error is returned if EOF is found.
+    fn parse_set_class_open(
+        &self,
+    ) -> Result<(ast::ClassBracketed, ast::ClassSetUnion)> {
+        assert_eq!(self.char(), '[');
+        let start = self.pos();
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::ClassUnclosed,
+            ));
+        }
+
+        let negated =
+            if self.char() != '^' {
+                false
+            } else {
+                if !self.bump_and_bump_space() {
+                    return Err(self.error(
+                        Span::new(start, self.pos()),
+                        ast::ErrorKind::ClassUnclosed,
+                    ));
+                }
+                true
+            };
+        // Accept any number of `-` as literal `-`.
+        let mut union = ast::ClassSetUnion {
+            span: self.span(),
+            items: vec![],
+        };
+        while self.char() == '-' {
+            union.push(ast::ClassSetItem::Literal(ast::Literal {
+                span: self.span_char(),
+                kind: ast::LiteralKind::Verbatim,
+                c: '-',
+            }));
+            if !self.bump_and_bump_space() {
+                return Err(self.error(
+                    Span::new(start, self.pos()),
+                    ast::ErrorKind::ClassUnclosed,
+                ));
+            }
+        }
+        // If `]` is the *first* char in a set, then interpret it as a literal
+        // `]`. That is, an empty class is impossible to write.
+        if union.items.is_empty() && self.char() == ']' {
+            union.push(ast::ClassSetItem::Literal(ast::Literal {
+                span: self.span_char(),
+                kind: ast::LiteralKind::Verbatim,
+                c: ']',
+            }));
+            if !self.bump_and_bump_space() {
+                return Err(self.error(
+                    Span::new(start, self.pos()),
+                    ast::ErrorKind::ClassUnclosed,
+                ));
+            }
+        }
+        let set = ast::ClassBracketed {
+            span: Span::new(start, self.pos()),
+            negated: negated,
+            kind: ast::ClassSet::union(ast::ClassSetUnion {
+                span: Span::new(union.span.start, union.span.start),
+                items: vec![],
+            }),
+        };
+        Ok((set, union))
+    }
+
+    /// Attempt to parse an ASCII character class, e.g., `[:alnum:]`.
+    ///
+    /// This assumes the parser is positioned at the opening `[`.
+    ///
+    /// If no valid ASCII character class could be found, then this does not
+    /// advance the parser and `None` is returned. Otherwise, the parser is
+    /// advanced to the first byte following the closing `]` and the
+    /// corresponding ASCII class is returned.
+    fn maybe_parse_ascii_class(&self) -> Option<ast::ClassAscii> {
+        // ASCII character classes are interesting from a parsing perspective
+        // because parsing cannot fail with any interesting error. For example,
+        // in order to use an ASCII character class, it must be enclosed in
+        // double brackets, e.g., `[[:alnum:]]`. Alternatively, you might think
+        // of it as "ASCII character characters have the syntax `[:NAME:]`
+        // which can only appear within character brackets." This means that
+        // things like `[[:lower:]A]` are legal constructs.
+        //
+        // However, if one types an incorrect ASCII character class, e.g.,
+        // `[[:loower:]]`, then we treat that as a normal nested character
+        // class containing the characters `:elorw`. One might argue that we
+        // should return an error instead since the repeated colons give away
+        // the intent to write an ASCII class. But what if the user typed
+        // `[[:lower]]` instead? How can we tell that was intended to be an
+        // ASCII class and not just a normal nested class?
+        //
+        // Reasonable people can probably disagree over this, but for better
+        // or worse, we implement semantics that never fails at the expense
+        // of better failure modes.
+        assert_eq!(self.char(), '[');
+        // If parsing fails, then we back up the parser to this starting point.
+        let start = self.pos();
+        let mut negated = false;
+        if !self.bump() || self.char() != ':' {
+            self.parser().pos.set(start);
+            return None;
+        }
+        if !self.bump() {
+            self.parser().pos.set(start);
+            return None;
+        }
+        if self.char() == '^' {
+            negated = true;
+            if !self.bump() {
+                self.parser().pos.set(start);
+                return None;
+            }
+        }
+        let name_start = self.offset();
+        while self.char() != ':' && self.bump() {}
+        if self.is_eof() {
+            self.parser().pos.set(start);
+            return None;
+        }
+        let name = &self.pattern()[name_start..self.offset()];
+        if !self.bump_if(":]") {
+            self.parser().pos.set(start);
+            return None;
+        }
+        let kind = match ast::ClassAsciiKind::from_name(name) {
+            Some(kind) => kind,
+            None => {
+                self.parser().pos.set(start);
+                return None;
+            }
+        };
+        Some(ast::ClassAscii {
+            span: Span::new(start, self.pos()),
+            kind: kind,
+            negated: negated,
+        })
+    }
+
+    /// Parse a Unicode class in either the single character notation, `\pN`
+    /// or the multi-character bracketed notation, `\p{Greek}`. This assumes
+    /// the parser is positioned at the `p` (or `P` for negation) and will
+    /// advance the parser to the character immediately following the class.
+    ///
+    /// Note that this does not check whether the class name is valid or not.
+    fn parse_unicode_class(&self) -> Result<ast::ClassUnicode> {
+        assert!(self.char() == 'p' || self.char() == 'P');
+
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        let negated = self.char() == 'P';
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        let (start, kind) =
+            if self.char() == '{' {
+                let start = self.span_char().end;
+                while self.bump_and_bump_space() && self.char() != '}' {
+                    scratch.push(self.char());
+                }
+                if self.is_eof() {
+                    return Err(self.error(
+                        self.span(),
+                        ast::ErrorKind::EscapeUnexpectedEof,
+                    ));
+                }
+                assert_eq!(self.char(), '}');
+                self.bump();
+
+                let name = scratch.as_str();
+                if let Some(i) = name.find("!=") {
+                    (start, ast::ClassUnicodeKind::NamedValue {
+                        op: ast::ClassUnicodeOpKind::NotEqual,
+                        name: name[..i].to_string(),
+                        value: name[i+2..].to_string(),
+                    })
+                } else if let Some(i) = name.find(':') {
+                    (start, ast::ClassUnicodeKind::NamedValue {
+                        op: ast::ClassUnicodeOpKind::Colon,
+                        name: name[..i].to_string(),
+                        value: name[i+1..].to_string(),
+                    })
+                } else if let Some(i) = name.find('=') {
+                    (start, ast::ClassUnicodeKind::NamedValue {
+                        op: ast::ClassUnicodeOpKind::Equal,
+                        name: name[..i].to_string(),
+                        value: name[i+1..].to_string(),
+                    })
+                } else {
+                    (start, ast::ClassUnicodeKind::Named(name.to_string()))
+                }
+            } else {
+                let start = self.pos();
+                let c = self.char();
+                self.bump_and_bump_space();
+                let kind = ast::ClassUnicodeKind::OneLetter(c);
+                (start, kind)
+            };
+        Ok(ast::ClassUnicode {
+            span: Span::new(start, self.pos()),
+            negated: negated,
+            kind: kind,
+        })
+    }
+
+    /// Parse a Perl character class, e.g., `\d` or `\W`. This assumes the
+    /// parser is currently at a valid character class name and will be
+    /// advanced to the character immediately following the class.
+    fn parse_perl_class(&self) -> ast::ClassPerl {
+        let c = self.char();
+        let span = self.span_char();
+        self.bump();
+        let (negated, kind) = match c {
+            'd' => (false, ast::ClassPerlKind::Digit),
+            'D' => (true, ast::ClassPerlKind::Digit),
+            's' => (false, ast::ClassPerlKind::Space),
+            'S' => (true, ast::ClassPerlKind::Space),
+            'w' => (false, ast::ClassPerlKind::Word),
+            'W' => (true, ast::ClassPerlKind::Word),
+            c => panic!("expected valid Perl class but got '{}'", c),
+        };
+        ast::ClassPerl { span: span, kind: kind, negated: negated }
+    }
+}
+
+/// A type that traverses a fully parsed Ast and checks whether its depth
+/// exceeds the specified nesting limit. If it does, then an error is returned.
+#[derive(Debug)]
+struct NestLimiter<'p, 's: 'p, P: 'p + 's> {
+    /// The parser that is checking the nest limit.
+    p: &'p ParserI<'s, P>,
+    /// The current depth while walking an Ast.
+    depth: u32,
+}
+
+impl<'p, 's, P: Borrow<Parser>> NestLimiter<'p, 's, P> {
+    fn new(p: &'p ParserI<'s, P>) -> NestLimiter<'p, 's, P> {
+        NestLimiter { p: p, depth: 0 }
+    }
+
+    fn check(self, ast: &Ast) -> Result<()> {
+        ast::visit(ast, self)
+    }
+
+    fn increment_depth(&mut self, span: &Span) -> Result<()> {
+        let new = self.depth.checked_add(1).ok_or_else(|| self.p.error(
+            span.clone(),
+            ast::ErrorKind::NestLimitExceeded(::std::u32::MAX),
+        ))?;
+        let limit = self.p.parser().nest_limit;
+        if new > limit {
+            return Err(self.p.error(
+                span.clone(),
+                ast::ErrorKind::NestLimitExceeded(limit),
+            ));
+        }
+        self.depth = new;
+        Ok(())
+    }
+
+    fn decrement_depth(&mut self) {
+        // Assuming the correctness of the visitor, this should never drop
+        // below 0.
+        self.depth = self.depth.checked_sub(1).unwrap();
+    }
+}
+
+impl<'p, 's, P: Borrow<Parser>> ast::Visitor for NestLimiter<'p, 's, P> {
+    type Output = ();
+    type Err = ast::Error;
+
+    fn finish(self) -> Result<()> {
+        Ok(())
+    }
+
+    fn visit_pre(&mut self, ast: &Ast) -> Result<()> {
+        let span = match *ast {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_)
+            | Ast::Class(ast::Class::Unicode(_))
+            | Ast::Class(ast::Class::Perl(_)) => {
+                // These are all base cases, so we don't increment depth.
+                return Ok(());
+            }
+            Ast::Class(ast::Class::Bracketed(ref x)) => &x.span,
+            Ast::Repetition(ref x) => &x.span,
+            Ast::Group(ref x) => &x.span,
+            Ast::Alternation(ref x) => &x.span,
+            Ast::Concat(ref x) => &x.span,
+        };
+        self.increment_depth(span)
+    }
+
+    fn visit_post(&mut self, ast: &Ast) -> Result<()> {
+        match *ast {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_)
+            | Ast::Class(ast::Class::Unicode(_))
+            | Ast::Class(ast::Class::Perl(_)) => {
+                // These are all base cases, so we don't decrement depth.
+                Ok(())
+            }
+            Ast::Class(ast::Class::Bracketed(_))
+            | Ast::Repetition(_)
+            | Ast::Group(_)
+            | Ast::Alternation(_)
+            | Ast::Concat(_) => {
+                self.decrement_depth();
+                Ok(())
+            }
+        }
+    }
+
+    fn visit_class_set_item_pre(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<()> {
+        let span = match *ast {
+            ast::ClassSetItem::Empty(_)
+            | ast::ClassSetItem::Literal(_)
+            | ast::ClassSetItem::Range(_)
+            | ast::ClassSetItem::Ascii(_)
+            | ast::ClassSetItem::Unicode(_)
+            | ast::ClassSetItem::Perl(_) => {
+                // These are all base cases, so we don't increment depth.
+                return Ok(());
+            }
+            ast::ClassSetItem::Bracketed(ref x) => &x.span,
+            ast::ClassSetItem::Union(ref x) => &x.span,
+        };
+        self.increment_depth(span)
+    }
+
+    fn visit_class_set_item_post(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<()> {
+        match *ast {
+            ast::ClassSetItem::Empty(_)
+            | ast::ClassSetItem::Literal(_)
+            | ast::ClassSetItem::Range(_)
+            | ast::ClassSetItem::Ascii(_)
+            | ast::ClassSetItem::Unicode(_)
+            | ast::ClassSetItem::Perl(_) => {
+                // These are all base cases, so we don't decrement depth.
+                Ok(())
+            }
+            ast::ClassSetItem::Bracketed(_)
+            | ast::ClassSetItem::Union(_) => {
+                self.decrement_depth();
+                Ok(())
+            }
+        }
+    }
+
+    fn visit_class_set_binary_op_pre(
+        &mut self,
+        ast: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        self.increment_depth(&ast.span)
+    }
+
+    fn visit_class_set_binary_op_post(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        self.decrement_depth();
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::ops::Range;
+
+    use ast::{self, Ast, Position, Span};
+    use super::{Parser, ParserI, ParserBuilder, Primitive};
+
+    // Our own assert_eq, which has slightly better formatting (but honestly
+    // still kind of crappy).
+    macro_rules! assert_eq {
+        ($left:expr, $right:expr) => ({
+            match (&$left, &$right) {
+                (left_val, right_val) => {
+                    if !(*left_val == *right_val) {
+                        panic!("assertion failed: `(left == right)`\n\n\
+                               left:  `{:?}`\nright: `{:?}`\n\n",
+                               left_val, right_val)
+                    }
+                }
+            }
+        });
+    }
+
+    // We create these errors to compare with real ast::Errors in the tests.
+    // We define equality between TestError and ast::Error to disregard the
+    // pattern string in ast::Error, which is annoying to provide in tests.
+    #[derive(Clone, Debug)]
+    struct TestError {
+        span: Span,
+        kind: ast::ErrorKind,
+    }
+
+    impl PartialEq<ast::Error> for TestError {
+        fn eq(&self, other: &ast::Error) -> bool {
+            self.span == other.span && self.kind == other.kind
+        }
+    }
+
+    impl PartialEq<TestError> for ast::Error {
+        fn eq(&self, other: &TestError) -> bool {
+            self.span == other.span && self.kind == other.kind
+        }
+    }
+
+    fn s(str: &str) -> String {
+        str.to_string()
+    }
+
+    fn parser(pattern: &str) -> ParserI<Parser> {
+        ParserI::new(Parser::new(), pattern)
+    }
+
+    fn parser_octal(pattern: &str) -> ParserI<Parser> {
+        let parser = ParserBuilder::new().octal(true).build();
+        ParserI::new(parser, pattern)
+    }
+
+    fn parser_nest_limit(pattern: &str, nest_limit: u32) -> ParserI<Parser> {
+        let p = ParserBuilder::new().nest_limit(nest_limit).build();
+        ParserI::new(p, pattern)
+    }
+
+    fn parser_ignore_whitespace(pattern: &str) -> ParserI<Parser> {
+        let p = ParserBuilder::new().ignore_whitespace(true).build();
+        ParserI::new(p, pattern)
+    }
+
+    /// Short alias for creating a new span.
+    fn nspan(start: Position, end: Position) -> Span {
+        Span::new(start, end)
+    }
+
+    /// Short alias for creating a new position.
+    fn npos(offset: usize, line: usize, column: usize) -> Position {
+        Position::new(offset, line, column)
+    }
+
+    /// Create a new span from the given offset range. This assumes a single
+    /// line and sets the columns based on the offsets. i.e., This only works
+    /// out of the box for ASCII, which is fine for most tests.
+    fn span(range: Range<usize>) -> Span {
+        let start = Position::new(range.start, 1, range.start + 1);
+        let end = Position::new(range.end, 1, range.end + 1);
+        Span::new(start, end)
+    }
+
+    /// Create a new span for the corresponding byte range in the given string.
+    fn span_range(subject: &str, range: Range<usize>) -> Span {
+        let start = Position {
+            offset: range.start,
+            line: 1 + subject[..range.start].matches('\n').count(),
+            column: 1 + subject[..range.start]
+                .chars()
+                .rev()
+                .position(|c| c == '\n')
+                .unwrap_or(subject[..range.start].chars().count()),
+        };
+        let end = Position {
+            offset: range.end,
+            line: 1 + subject[..range.end].matches('\n').count(),
+            column: 1 + subject[..range.end]
+                .chars()
+                .rev()
+                .position(|c| c == '\n')
+                .unwrap_or(subject[..range.end].chars().count()),
+        };
+        Span::new(start, end)
+    }
+
+    /// Create a verbatim literal starting at the given position.
+    fn lit(c: char, start: usize) -> Ast {
+        lit_with(c, span(start..start + c.len_utf8()))
+    }
+
+    /// Create a punctuation literal starting at the given position.
+    fn punct_lit(c: char, span: Span) -> Ast {
+        Ast::Literal(ast::Literal {
+            span: span,
+            kind: ast::LiteralKind::Punctuation,
+            c: c,
+        })
+    }
+
+    /// Create a verbatim literal with the given span.
+    fn lit_with(c: char, span: Span) -> Ast {
+        Ast::Literal(ast::Literal {
+            span: span,
+            kind: ast::LiteralKind::Verbatim,
+            c: c,
+        })
+    }
+
+    /// Create a concatenation with the given range.
+    fn concat(range: Range<usize>, asts: Vec<Ast>) -> Ast {
+        concat_with(span(range), asts)
+    }
+
+    /// Create a concatenation with the given span.
+    fn concat_with(span: Span, asts: Vec<Ast>) -> Ast {
+        Ast::Concat(ast::Concat { span: span, asts: asts })
+    }
+
+    /// Create an alternation with the given span.
+    fn alt(range: Range<usize>, asts: Vec<Ast>) -> Ast {
+        Ast::Alternation(ast::Alternation { span: span(range), asts: asts })
+    }
+
+    /// Create a capturing group with the given span.
+    fn group(range: Range<usize>, index: u32, ast: Ast) -> Ast {
+        Ast::Group(ast::Group {
+            span: span(range),
+            kind: ast::GroupKind::CaptureIndex(index),
+            ast: Box::new(ast),
+        })
+    }
+
+    /// Create an ast::SetFlags.
+    ///
+    /// The given pattern should be the full pattern string. The range given
+    /// should correspond to the byte offsets where the flag set occurs.
+    ///
+    /// If negated is true, then the set is interpreted as beginning with a
+    /// negation.
+    fn flag_set(
+        pat: &str,
+        range: Range<usize>,
+        flag: ast::Flag,
+        negated: bool,
+    ) -> Ast {
+        let mut items = vec![
+            ast::FlagsItem {
+                span: span_range(pat, (range.end - 2)..(range.end - 1)),
+                kind: ast::FlagsItemKind::Flag(flag),
+            },
+        ];
+        if negated {
+            items.insert(0, ast::FlagsItem {
+                span: span_range(pat, (range.start + 2)..(range.end - 2)),
+                kind: ast::FlagsItemKind::Negation,
+            });
+        }
+        Ast::Flags(ast::SetFlags {
+            span: span_range(pat, range.clone()),
+            flags: ast::Flags {
+                span: span_range(pat, (range.start + 2)..(range.end - 1)),
+                items: items,
+            },
+        })
+    }
+
+    #[test]
+    fn parse_nest_limit() {
+        // A nest limit of 0 still allows some types of regexes.
+        assert_eq!(
+            parser_nest_limit("", 0).parse(),
+            Ok(Ast::Empty(span(0..0))));
+        assert_eq!(
+            parser_nest_limit("a", 0).parse(),
+            Ok(lit('a', 0)));
+
+        // Test repetition operations, which require one level of nesting.
+        assert_eq!(
+            parser_nest_limit("a+", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("a+", 1).parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::OneOrMore,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser_nest_limit("(a)+", 1).parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("a+*", 1).parse().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("a+*", 2).parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..3),
+                op: ast::RepetitionOp {
+                    span: span(2..3),
+                    kind: ast::RepetitionKind::ZeroOrMore,
+                },
+                greedy: true,
+                ast: Box::new(Ast::Repetition(ast::Repetition {
+                    span: span(0..2),
+                    op: ast::RepetitionOp {
+                        span: span(1..2),
+                        kind: ast::RepetitionKind::OneOrMore,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('a', 0)),
+                })),
+            })));
+
+        // Test concatenations. A concatenation requires one level of nesting.
+        assert_eq!(
+            parser_nest_limit("ab", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("ab", 1).parse(),
+            Ok(concat(0..2, vec![lit('a', 0), lit('b', 1)])));
+        assert_eq!(
+            parser_nest_limit("abc", 1).parse(),
+            Ok(concat(0..3, vec![lit('a', 0), lit('b', 1), lit('c', 2)])));
+
+        // Test alternations. An alternation requires one level of nesting.
+        assert_eq!(
+            parser_nest_limit("a|b", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("a|b", 1).parse(),
+            Ok(alt(0..3, vec![lit('a', 0), lit('b', 2)])));
+        assert_eq!(
+            parser_nest_limit("a|b|c", 1).parse(),
+            Ok(alt(0..5, vec![lit('a', 0), lit('b', 2), lit('c', 4)])));
+
+        // Test character classes. Classes form their own mini-recursive
+        // syntax!
+        assert_eq!(
+            parser_nest_limit("[a]", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("[a]", 1).parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..3),
+                negated: false,
+                kind: ast::ClassSet::Item(
+                    ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(1..2),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'a',
+                    })
+                ),
+            }))));
+        assert_eq!(
+            parser_nest_limit("[ab]", 1).parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("[ab[cd]]", 2).parse().unwrap_err(),
+            TestError {
+                span: span(3..7),
+                kind: ast::ErrorKind::NestLimitExceeded(2),
+            });
+        assert_eq!(
+            parser_nest_limit("[ab[cd]]", 3).parse().unwrap_err(),
+            TestError {
+                span: span(4..6),
+                kind: ast::ErrorKind::NestLimitExceeded(3),
+            });
+        assert_eq!(
+            parser_nest_limit("[a--b]", 1).parse().unwrap_err(),
+            TestError {
+                span: span(1..5),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("[a--bc]", 2).parse().unwrap_err(),
+            TestError {
+                span: span(4..6),
+                kind: ast::ErrorKind::NestLimitExceeded(2),
+            });
+    }
+
+    #[test]
+    fn parse_comments() {
+        let pat = "(?x)
+# This is comment 1.
+foo # This is comment 2.
+  # This is comment 3.
+bar
+# This is comment 4.";
+        let astc = parser(pat).parse_with_comments().unwrap();
+        assert_eq!(
+            astc.ast,
+            concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                lit_with('f', span_range(pat, 26..27)),
+                lit_with('o', span_range(pat, 27..28)),
+                lit_with('o', span_range(pat, 28..29)),
+                lit_with('b', span_range(pat, 74..75)),
+                lit_with('a', span_range(pat, 75..76)),
+                lit_with('r', span_range(pat, 76..77)),
+            ]));
+        assert_eq!(astc.comments, vec![
+            ast::Comment {
+                span: span_range(pat, 5..26),
+                comment: s(" This is comment 1."),
+            },
+            ast::Comment {
+                span: span_range(pat, 30..51),
+                comment: s(" This is comment 2."),
+            },
+            ast::Comment {
+                span: span_range(pat, 53..74),
+                comment: s(" This is comment 3."),
+            },
+            ast::Comment {
+                span: span_range(pat, 78..98),
+                comment: s(" This is comment 4."),
+            },
+        ]);
+    }
+
+    #[test]
+    fn parse_holistic() {
+        assert_eq!(
+            parser("]").parse(),
+            Ok(lit(']', 0)));
+        assert_eq!(
+            parser(r"\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#\&\-\~").parse(),
+            Ok(concat(0..36, vec![
+                punct_lit('\\', span(0..2)),
+                punct_lit('.', span(2..4)),
+                punct_lit('+', span(4..6)),
+                punct_lit('*', span(6..8)),
+                punct_lit('?', span(8..10)),
+                punct_lit('(', span(10..12)),
+                punct_lit(')', span(12..14)),
+                punct_lit('|', span(14..16)),
+                punct_lit('[', span(16..18)),
+                punct_lit(']', span(18..20)),
+                punct_lit('{', span(20..22)),
+                punct_lit('}', span(22..24)),
+                punct_lit('^', span(24..26)),
+                punct_lit('$', span(26..28)),
+                punct_lit('#', span(28..30)),
+                punct_lit('&', span(30..32)),
+                punct_lit('-', span(32..34)),
+                punct_lit('~', span(34..36)),
+            ])));
+    }
+
+    #[test]
+    fn parse_ignore_whitespace() {
+        // Test that basic whitespace insensitivity works.
+        let pat = "(?x)a b";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(nspan(npos(0, 1, 1), npos(7, 1, 8)), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                lit_with('a', nspan(npos(4, 1, 5), npos(5, 1, 6))),
+                lit_with('b', nspan(npos(6, 1, 7), npos(7, 1, 8))),
+            ])));
+
+        // Test that we can toggle whitespace insensitivity.
+        let pat = "(?x)a b(?-x)a b";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(nspan(npos(0, 1, 1), npos(15, 1, 16)), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                lit_with('a', nspan(npos(4, 1, 5), npos(5, 1, 6))),
+                lit_with('b', nspan(npos(6, 1, 7), npos(7, 1, 8))),
+                flag_set(pat, 7..12, ast::Flag::IgnoreWhitespace, true),
+                lit_with('a', nspan(npos(12, 1, 13), npos(13, 1, 14))),
+                lit_with(' ', nspan(npos(13, 1, 14), npos(14, 1, 15))),
+                lit_with('b', nspan(npos(14, 1, 15), npos(15, 1, 16))),
+            ])));
+
+        // Test that nesting whitespace insensitive flags works.
+        let pat = "a (?x:a )a ";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..11), vec![
+                lit_with('a', span_range(pat, 0..1)),
+                lit_with(' ', span_range(pat, 1..2)),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 2..9),
+                    kind: ast::GroupKind::NonCapturing(ast::Flags {
+                        span: span_range(pat, 4..5),
+                        items: vec![
+                            ast::FlagsItem {
+                                span: span_range(pat, 4..5),
+                                kind: ast::FlagsItemKind::Flag(
+                                    ast::Flag::IgnoreWhitespace),
+                            },
+                        ],
+                    }),
+                    ast: Box::new(lit_with('a', span_range(pat, 6..7))),
+                }),
+                lit_with('a', span_range(pat, 9..10)),
+                lit_with(' ', span_range(pat, 10..11)),
+            ])));
+
+        // Test that whitespace after an opening paren is insignificant.
+        let pat = "(?x)( ?P<foo> a )";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 4..pat.len()),
+                    kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                        span: span_range(pat, 9..12),
+                        name: s("foo"),
+                        index: 1,
+                    }),
+                    ast: Box::new(lit_with('a', span_range(pat, 14..15))),
+                }),
+            ])));
+        let pat = "(?x)(  a )";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 4..pat.len()),
+                    kind: ast::GroupKind::CaptureIndex(1),
+                    ast: Box::new(lit_with('a', span_range(pat, 7..8))),
+                }),
+            ])));
+        let pat = "(?x)(  ?:  a )";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 4..pat.len()),
+                    kind: ast::GroupKind::NonCapturing(ast::Flags {
+                        span: span_range(pat, 8..8),
+                        items: vec![],
+                    }),
+                    ast: Box::new(lit_with('a', span_range(pat, 11..12))),
+                }),
+            ])));
+        let pat = r"(?x)\x { 53 }";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Literal(ast::Literal {
+                    span: span(4..13),
+                    kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                    c: 'S',
+                }),
+            ])));
+
+        // Test that whitespace after an escape is OK.
+        let pat = r"(?x)\ ";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Literal(ast::Literal {
+                    span: span_range(pat, 4..6),
+                    kind: ast::LiteralKind::Special(
+                        ast::SpecialLiteralKind::Space),
+                    c: ' ',
+                }),
+            ])));
+        // ... but only when `x` mode is enabled.
+        let pat = r"\ ";
+        assert_eq!(
+            parser(pat).parse().unwrap_err(),
+            TestError {
+                span: span_range(pat, 0..2),
+                kind: ast::ErrorKind::EscapeUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_newlines() {
+        let pat = ".\n.";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..3), vec![
+                Ast::Dot(span_range(pat, 0..1)),
+                lit_with('\n', span_range(pat, 1..2)),
+                Ast::Dot(span_range(pat, 2..3)),
+            ])));
+
+        let pat = "foobar\nbaz\nquux\n";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                lit_with('f', nspan(npos(0, 1, 1), npos(1, 1, 2))),
+                lit_with('o', nspan(npos(1, 1, 2), npos(2, 1, 3))),
+                lit_with('o', nspan(npos(2, 1, 3), npos(3, 1, 4))),
+                lit_with('b', nspan(npos(3, 1, 4), npos(4, 1, 5))),
+                lit_with('a', nspan(npos(4, 1, 5), npos(5, 1, 6))),
+                lit_with('r', nspan(npos(5, 1, 6), npos(6, 1, 7))),
+                lit_with('\n', nspan(npos(6, 1, 7), npos(7, 2, 1))),
+                lit_with('b', nspan(npos(7, 2, 1), npos(8, 2, 2))),
+                lit_with('a', nspan(npos(8, 2, 2), npos(9, 2, 3))),
+                lit_with('z', nspan(npos(9, 2, 3), npos(10, 2, 4))),
+                lit_with('\n', nspan(npos(10, 2, 4), npos(11, 3, 1))),
+                lit_with('q', nspan(npos(11, 3, 1), npos(12, 3, 2))),
+                lit_with('u', nspan(npos(12, 3, 2), npos(13, 3, 3))),
+                lit_with('u', nspan(npos(13, 3, 3), npos(14, 3, 4))),
+                lit_with('x', nspan(npos(14, 3, 4), npos(15, 3, 5))),
+                lit_with('\n', nspan(npos(15, 3, 5), npos(16, 4, 1))),
+            ])));
+    }
+
+    #[test]
+    fn parse_uncounted_repetition() {
+        assert_eq!(
+            parser(r"a*").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::ZeroOrMore,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a+").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::OneOrMore,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+
+        assert_eq!(
+            parser(r"a?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a??").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..3),
+                op: ast::RepetitionOp {
+                    span: span(1..3),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: false,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a?b").parse(),
+            Ok(concat(0..3, vec![
+                Ast::Repetition(ast::Repetition {
+                    span: span(0..2),
+                    op: ast::RepetitionOp {
+                        span: span(1..2),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('a', 0)),
+                }),
+                lit('b', 2),
+            ])));
+        assert_eq!(
+            parser(r"a??b").parse(),
+            Ok(concat(0..4, vec![
+                Ast::Repetition(ast::Repetition {
+                    span: span(0..3),
+                    op: ast::RepetitionOp {
+                        span: span(1..3),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: false,
+                    ast: Box::new(lit('a', 0)),
+                }),
+                lit('b', 3),
+            ])));
+        assert_eq!(
+            parser(r"ab?").parse(),
+            Ok(concat(0..3, vec![
+                lit('a', 0),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..3),
+                    op: ast::RepetitionOp {
+                        span: span(2..3),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('b', 1)),
+                }),
+            ])));
+        assert_eq!(
+            parser(r"(ab)?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..5),
+                op: ast::RepetitionOp {
+                    span: span(4..5),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: true,
+                ast: Box::new(group(0..4, 1, concat(1..3, vec![
+                    lit('a', 1),
+                    lit('b', 2),
+                ]))),
+            })));
+        assert_eq!(
+            parser(r"|a?").parse(),
+            Ok(alt(0..3, vec![
+                Ast::Empty(span(0..0)),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..3),
+                    op: ast::RepetitionOp {
+                        span: span(2..3),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('a', 1)),
+                }),
+            ])));
+
+        assert_eq!(
+            parser(r"*").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(?i)*").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(*)").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(?:?)").parse().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"+").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"?").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(?)").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|*").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|+").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|?").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+    }
+
+    #[test]
+    fn parse_counted_repetition() {
+        assert_eq!(
+            parser(r"a{5}").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..4),
+                op: ast::RepetitionOp {
+                    span: span(1..4),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Exactly(5)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{5,}").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..5),
+                op: ast::RepetitionOp {
+                    span: span(1..5),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::AtLeast(5)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{5,9}").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..6),
+                op: ast::RepetitionOp {
+                    span: span(1..6),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Bounded(5, 9)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{5}?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..5),
+                op: ast::RepetitionOp {
+                    span: span(1..5),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Exactly(5)),
+                },
+                greedy: false,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"ab{5}").parse(),
+            Ok(concat(0..5, vec![
+                lit('a', 0),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..5),
+                    op: ast::RepetitionOp {
+                        span: span(2..5),
+                        kind: ast::RepetitionKind::Range(
+                            ast::RepetitionRange::Exactly(5)),
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('b', 1)),
+                }),
+            ])));
+        assert_eq!(
+            parser(r"ab{5}c").parse(),
+            Ok(concat(0..6, vec![
+                lit('a', 0),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..5),
+                    op: ast::RepetitionOp {
+                        span: span(2..5),
+                        kind: ast::RepetitionKind::Range(
+                            ast::RepetitionRange::Exactly(5)),
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('b', 1)),
+                }),
+                lit('c', 5),
+            ])));
+
+        assert_eq!(
+            parser(r"a{ 5 }").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..6),
+                op: ast::RepetitionOp {
+                    span: span(1..6),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Exactly(5)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{ 5 , 9 }").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..10),
+                op: ast::RepetitionOp {
+                    span: span(1..10),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Bounded(5, 9)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser_ignore_whitespace(r"a{5,9} ?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..8),
+                op: ast::RepetitionOp {
+                    span: span(1..8),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Bounded(5, 9)),
+                },
+                greedy: false,
+                ast: Box::new(lit('a', 0)),
+            })));
+
+        assert_eq!(
+            parser(r"a{").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{}").parse().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser(r"a{a").parse().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser(r"a{9999999999}").parse().unwrap_err(),
+            TestError {
+                span: span(2..12),
+                kind: ast::ErrorKind::DecimalInvalid,
+            });
+        assert_eq!(
+            parser(r"a{9").parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{9,a").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser(r"a{9,9999999999}").parse().unwrap_err(),
+            TestError {
+                span: span(4..14),
+                kind: ast::ErrorKind::DecimalInvalid,
+            });
+        assert_eq!(
+            parser(r"a{9,").parse().unwrap_err(),
+            TestError {
+                span: span(1..4),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{9,11").parse().unwrap_err(),
+            TestError {
+                span: span(1..6),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{2,1}").parse().unwrap_err(),
+            TestError {
+                span: span(1..6),
+                kind: ast::ErrorKind::RepetitionCountInvalid,
+            });
+        assert_eq!(
+            parser(r"{5}").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|{5}").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+    }
+
+    #[test]
+    fn parse_alternate() {
+        assert_eq!(
+            parser(r"a|b").parse(),
+            Ok(Ast::Alternation(ast::Alternation {
+                span: span(0..3),
+                asts: vec![lit('a', 0), lit('b', 2)],
+            })));
+        assert_eq!(
+            parser(r"(a|b)").parse(),
+            Ok(group(0..5, 1, Ast::Alternation(ast::Alternation {
+                span: span(1..4),
+                asts: vec![lit('a', 1), lit('b', 3)],
+            }))));
+
+        assert_eq!(
+            parser(r"a|b|c").parse(),
+            Ok(Ast::Alternation(ast::Alternation {
+                span: span(0..5),
+                asts: vec![lit('a', 0), lit('b', 2), lit('c', 4)],
+            })));
+        assert_eq!(
+            parser(r"ax|by|cz").parse(),
+            Ok(Ast::Alternation(ast::Alternation {
+                span: span(0..8),
+                asts: vec![
+                    concat(0..2, vec![lit('a', 0), lit('x', 1)]),
+                    concat(3..5, vec![lit('b', 3), lit('y', 4)]),
+                    concat(6..8, vec![lit('c', 6), lit('z', 7)]),
+                ],
+            })));
+        assert_eq!(
+            parser(r"(ax|by|cz)").parse(),
+            Ok(group(0..10, 1, Ast::Alternation(ast::Alternation {
+                span: span(1..9),
+                asts: vec![
+                    concat(1..3, vec![lit('a', 1), lit('x', 2)]),
+                    concat(4..6, vec![lit('b', 4), lit('y', 5)]),
+                    concat(7..9, vec![lit('c', 7), lit('z', 8)]),
+                ],
+            }))));
+        assert_eq!(
+            parser(r"(ax|(by|(cz)))").parse(),
+            Ok(group(0..14, 1, alt(1..13, vec![
+                concat(1..3, vec![lit('a', 1), lit('x', 2)]),
+                group(4..13, 2, alt(5..12, vec![
+                    concat(5..7, vec![lit('b', 5), lit('y', 6)]),
+                    group(8..12, 3, concat(9..11, vec![
+                        lit('c', 9),
+                        lit('z', 10),
+                    ])),
+                ])),
+            ]))));
+
+        assert_eq!(
+            parser(r"|").parse(), Ok(alt(0..1, vec![
+                Ast::Empty(span(0..0)), Ast::Empty(span(1..1)),
+            ])));
+        assert_eq!(
+            parser(r"||").parse(), Ok(alt(0..2, vec![
+                Ast::Empty(span(0..0)),
+                Ast::Empty(span(1..1)),
+                Ast::Empty(span(2..2)),
+            ])));
+        assert_eq!(
+            parser(r"a|").parse(), Ok(alt(0..2, vec![
+                lit('a', 0), Ast::Empty(span(2..2)),
+            ])));
+        assert_eq!(
+            parser(r"|a").parse(), Ok(alt(0..2, vec![
+                Ast::Empty(span(0..0)), lit('a', 1),
+            ])));
+
+        assert_eq!(
+            parser(r"(|)").parse(), Ok(group(0..3, 1, alt(1..2, vec![
+                Ast::Empty(span(1..1)), Ast::Empty(span(2..2)),
+            ]))));
+        assert_eq!(
+            parser(r"(a|)").parse(), Ok(group(0..4, 1, alt(1..3, vec![
+                lit('a', 1), Ast::Empty(span(3..3)),
+            ]))));
+        assert_eq!(
+            parser(r"(|a)").parse(), Ok(group(0..4, 1, alt(1..3, vec![
+                Ast::Empty(span(1..1)), lit('a', 2),
+            ]))));
+
+        assert_eq!(
+            parser(r"a|b)").parse().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::GroupUnopened,
+            });
+        assert_eq!(
+            parser(r"(a|b").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+    }
+
+    #[test]
+    fn parse_unsupported_lookaround() {
+        assert_eq!(
+            parser(r"(?=a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+        assert_eq!(
+            parser(r"(?!a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+        assert_eq!(
+            parser(r"(?<=a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..4),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+        assert_eq!(
+            parser(r"(?<!a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..4),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+    }
+
+    #[test]
+    fn parse_group() {
+        assert_eq!(parser("(?i)").parse(), Ok(Ast::Flags(ast::SetFlags {
+            span: span(0..4),
+            flags: ast::Flags {
+                span: span(2..3),
+                items: vec![ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                }],
+            },
+        })));
+        assert_eq!(parser("(?iU)").parse(), Ok(Ast::Flags(ast::SetFlags {
+            span: span(0..5),
+            flags: ast::Flags {
+                span: span(2..4),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                    ast::FlagsItem {
+                        span: span(3..4),
+                        kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                    },
+                ],
+            },
+        })));
+        assert_eq!(parser("(?i-U)").parse(), Ok(Ast::Flags(ast::SetFlags {
+            span: span(0..6),
+            flags: ast::Flags {
+                span: span(2..5),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                    ast::FlagsItem {
+                        span: span(3..4),
+                        kind: ast::FlagsItemKind::Negation,
+                    },
+                    ast::FlagsItem {
+                        span: span(4..5),
+                        kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                    },
+                ],
+            },
+        })));
+
+        assert_eq!(parser("()").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..2),
+            kind: ast::GroupKind::CaptureIndex(1),
+            ast: Box::new(Ast::Empty(span(1..1))),
+        })));
+        assert_eq!(parser("(a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..3),
+            kind: ast::GroupKind::CaptureIndex(1),
+            ast: Box::new(lit('a', 1)),
+        })));
+        assert_eq!(parser("(())").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..4),
+            kind: ast::GroupKind::CaptureIndex(1),
+            ast: Box::new(Ast::Group(ast::Group {
+                span: span(1..3),
+                kind: ast::GroupKind::CaptureIndex(2),
+                ast: Box::new(Ast::Empty(span(2..2))),
+            })),
+        })));
+
+        assert_eq!(parser("(?:a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..5),
+            kind: ast::GroupKind::NonCapturing(ast::Flags {
+                span: span(2..2),
+                items: vec![],
+            }),
+            ast: Box::new(lit('a', 3)),
+        })));
+
+        assert_eq!(parser("(?i:a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..6),
+            kind: ast::GroupKind::NonCapturing(ast::Flags {
+                span: span(2..3),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                ],
+            }),
+            ast: Box::new(lit('a', 4)),
+        })));
+        assert_eq!(parser("(?i-U:a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..8),
+            kind: ast::GroupKind::NonCapturing(ast::Flags {
+                span: span(2..5),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                    ast::FlagsItem {
+                        span: span(3..4),
+                        kind: ast::FlagsItemKind::Negation,
+                    },
+                    ast::FlagsItem {
+                        span: span(4..5),
+                        kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                    },
+                ],
+            }),
+            ast: Box::new(lit('a', 6)),
+        })));
+
+        assert_eq!(
+            parser("(").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser("(?").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser("(?P").parse().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+        assert_eq!(
+            parser("(?P<").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(a").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser("(()").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser(")").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnopened,
+            });
+        assert_eq!(
+            parser("a)").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::GroupUnopened,
+            });
+    }
+
+    #[test]
+    fn parse_capture_name() {
+        assert_eq!(parser("(?P<a>z)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..8),
+            kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                span: span(4..5),
+                name: s("a"),
+                index: 1,
+            }),
+            ast: Box::new(lit('z', 6)),
+        })));
+        assert_eq!(parser("(?P<abc>z)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..10),
+            kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                span: span(4..7),
+                name: s("abc"),
+                index: 1,
+            }),
+            ast: Box::new(lit('z', 8)),
+        })));
+
+        assert_eq!(
+            parser("(?P<").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(?P<>z)").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::GroupNameEmpty,
+            });
+        assert_eq!(
+            parser("(?P<a").parse().unwrap_err(),
+            TestError {
+                span: span(5..5),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(?P<ab").parse().unwrap_err(),
+            TestError {
+                span: span(6..6),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(?P<0a").parse().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::GroupNameInvalid,
+            });
+        assert_eq!(
+            parser("(?P<~").parse().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::GroupNameInvalid,
+            });
+        assert_eq!(
+            parser("(?P<abc~").parse().unwrap_err(),
+            TestError {
+                span: span(7..8),
+                kind: ast::ErrorKind::GroupNameInvalid,
+            });
+        assert_eq!(
+            parser("(?P<a>y)(?P<a>z)").parse().unwrap_err(),
+            TestError {
+                span: span(12..13),
+                kind: ast::ErrorKind::GroupNameDuplicate {
+                    original: span(4..5),
+                },
+            });
+    }
+
+    #[test]
+    fn parse_flags() {
+        assert_eq!(parser("i:").parse_flags(), Ok(ast::Flags {
+            span: span(0..1),
+            items: vec![ast::FlagsItem {
+                span: span(0..1),
+                kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+            }],
+        }));
+        assert_eq!(parser("i)").parse_flags(), Ok(ast::Flags {
+            span: span(0..1),
+            items: vec![ast::FlagsItem {
+                span: span(0..1),
+                kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+            }],
+        }));
+
+        assert_eq!(parser("isU:").parse_flags(), Ok(ast::Flags {
+            span: span(0..3),
+            items: vec![
+                ast::FlagsItem {
+                    span: span(0..1),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                },
+                ast::FlagsItem {
+                    span: span(1..2),
+                    kind: ast::FlagsItemKind::Flag(
+                        ast::Flag::DotMatchesNewLine),
+                },
+                ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                },
+            ],
+        }));
+
+        assert_eq!(parser("-isU:").parse_flags(), Ok(ast::Flags {
+            span: span(0..4),
+            items: vec![
+                ast::FlagsItem {
+                    span: span(0..1),
+                    kind: ast::FlagsItemKind::Negation,
+                },
+                ast::FlagsItem {
+                    span: span(1..2),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                },
+                ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(
+                        ast::Flag::DotMatchesNewLine),
+                },
+                ast::FlagsItem {
+                    span: span(3..4),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                },
+            ],
+        }));
+        assert_eq!(parser("i-sU:").parse_flags(), Ok(ast::Flags {
+            span: span(0..4),
+            items: vec![
+                ast::FlagsItem {
+                    span: span(0..1),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                },
+                ast::FlagsItem {
+                    span: span(1..2),
+                    kind: ast::FlagsItemKind::Negation,
+                },
+                ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(
+                        ast::Flag::DotMatchesNewLine),
+                },
+                ast::FlagsItem {
+                    span: span(3..4),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                },
+            ],
+        }));
+
+        assert_eq!(
+            parser("isU").parse_flags().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::FlagUnexpectedEof,
+            });
+        assert_eq!(
+            parser("isUa:").parse_flags().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+        assert_eq!(
+            parser("isUi:").parse_flags().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::FlagDuplicate {
+                    original: span(0..1),
+                },
+            });
+        assert_eq!(
+            parser("i-sU-i:").parse_flags().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::FlagRepeatedNegation {
+                    original: span(1..2),
+                },
+            });
+        assert_eq!(
+            parser("-)").parse_flags().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::FlagDanglingNegation,
+            });
+        assert_eq!(
+            parser("i-)").parse_flags().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::FlagDanglingNegation,
+            });
+        assert_eq!(
+            parser("iU-)").parse_flags().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::FlagDanglingNegation,
+            });
+    }
+
+    #[test]
+    fn parse_flag() {
+        assert_eq!(parser("i").parse_flag(), Ok(ast::Flag::CaseInsensitive));
+        assert_eq!(parser("m").parse_flag(), Ok(ast::Flag::MultiLine));
+        assert_eq!(parser("s").parse_flag(), Ok(ast::Flag::DotMatchesNewLine));
+        assert_eq!(parser("U").parse_flag(), Ok(ast::Flag::SwapGreed));
+        assert_eq!(parser("u").parse_flag(), Ok(ast::Flag::Unicode));
+        assert_eq!(parser("x").parse_flag(), Ok(ast::Flag::IgnoreWhitespace));
+
+        assert_eq!(
+            parser("a").parse_flag().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+        assert_eq!(
+            parser("☃").parse_flag().unwrap_err(),
+            TestError {
+                span: span_range("☃", 0..3),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_primitive_non_escape() {
+        assert_eq!(
+            parser(r".").parse_primitive(),
+            Ok(Primitive::Dot(span(0..1))));
+        assert_eq!(
+            parser(r"^").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..1),
+                kind: ast::AssertionKind::StartLine,
+            })));
+        assert_eq!(
+            parser(r"$").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..1),
+                kind: ast::AssertionKind::EndLine,
+            })));
+
+        assert_eq!(
+            parser(r"a").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..1),
+                kind: ast::LiteralKind::Verbatim,
+                c: 'a',
+            })));
+        assert_eq!(
+            parser(r"|").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..1),
+                kind: ast::LiteralKind::Verbatim,
+                c: '|',
+            })));
+        assert_eq!(
+            parser(r"☃").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span_range("☃", 0..3),
+                kind: ast::LiteralKind::Verbatim,
+                c: '☃',
+            })));
+    }
+
+    #[test]
+    fn parse_escape() {
+        assert_eq!(
+            parser(r"\|").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..2),
+                kind: ast::LiteralKind::Punctuation,
+                c: '|',
+            })));
+        let specials = &[
+            (r"\a", '\x07', ast::SpecialLiteralKind::Bell),
+            (r"\f", '\x0C', ast::SpecialLiteralKind::FormFeed),
+            (r"\t", '\t', ast::SpecialLiteralKind::Tab),
+            (r"\n", '\n', ast::SpecialLiteralKind::LineFeed),
+            (r"\r", '\r', ast::SpecialLiteralKind::CarriageReturn),
+            (r"\v", '\x0B', ast::SpecialLiteralKind::VerticalTab),
+        ];
+        for &(pat, c, ref kind) in specials {
+            assert_eq!(
+                parser(pat).parse_primitive(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..2),
+                    kind: ast::LiteralKind::Special(kind.clone()),
+                    c: c,
+                })));
+        }
+        assert_eq!(
+            parser(r"\A").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::StartText,
+            })));
+        assert_eq!(
+            parser(r"\z").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::EndText,
+            })));
+        assert_eq!(
+            parser(r"\b").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::WordBoundary,
+            })));
+        assert_eq!(
+            parser(r"\B").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::NotWordBoundary,
+            })));
+
+        assert_eq!(
+            parser(r"\").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\y").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::EscapeUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_unsupported_backreference() {
+        assert_eq!(
+            parser(r"\0").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::UnsupportedBackreference,
+            });
+        assert_eq!(
+            parser(r"\9").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::UnsupportedBackreference,
+            });
+    }
+
+    #[test]
+    fn parse_octal() {
+        for i in 0..511 {
+            let pat = format!(r"\{:o}", i);
+            assert_eq!(
+                parser_octal(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::Octal,
+                    c: ::std::char::from_u32(i).unwrap(),
+                })));
+        }
+        assert_eq!(
+            parser_octal(r"\778").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..3),
+                kind: ast::LiteralKind::Octal,
+                c: '?',
+            })));
+        assert_eq!(
+            parser_octal(r"\7777").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..4),
+                kind: ast::LiteralKind::Octal,
+                c: '\u{01FF}',
+            })));
+        assert_eq!(
+            parser_octal(r"\778").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..4),
+                asts: vec![
+                    Ast::Literal(ast::Literal {
+                        span: span(0..3),
+                        kind: ast::LiteralKind::Octal,
+                        c: '?',
+                    }),
+                    Ast::Literal(ast::Literal {
+                        span: span(3..4),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '8',
+                    }),
+                ],
+            })));
+        assert_eq!(
+            parser_octal(r"\7777").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..5),
+                asts: vec![
+                    Ast::Literal(ast::Literal {
+                        span: span(0..4),
+                        kind: ast::LiteralKind::Octal,
+                        c: '\u{01FF}',
+                    }),
+                    Ast::Literal(ast::Literal {
+                        span: span(4..5),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '7',
+                    }),
+                ],
+            })));
+
+        assert_eq!(
+            parser_octal(r"\8").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::EscapeUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_hex_two() {
+        for i in 0..256 {
+            let pat = format!(r"\x{:02x}", i);
+            assert_eq!(
+                parser(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::HexFixed(ast::HexLiteralKind::X),
+                    c: ::std::char::from_u32(i).unwrap(),
+                })));
+        }
+
+        assert_eq!(
+            parser(r"\xF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\xG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\xFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+    }
+
+    #[test]
+    fn parse_hex_four() {
+        for i in 0..65536 {
+            let c = match ::std::char::from_u32(i) {
+                None => continue,
+                Some(c) => c,
+            };
+            let pat = format!(r"\u{:04x}", i);
+            assert_eq!(
+                parser(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::HexFixed(
+                        ast::HexLiteralKind::UnicodeShort),
+                    c: c,
+                })));
+        }
+
+        assert_eq!(
+            parser(r"\uF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\uG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(5..6),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uD800").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..6),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+    }
+
+    #[test]
+    fn parse_hex_eight() {
+        for i in 0..65536 {
+            let c = match ::std::char::from_u32(i) {
+                None => continue,
+                Some(c) => c,
+            };
+            let pat = format!(r"\U{:08x}", i);
+            assert_eq!(
+                parser(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::HexFixed(
+                        ast::HexLiteralKind::UnicodeLong),
+                    c: c,
+                })));
+        }
+
+        assert_eq!(
+            parser(r"\UF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\UG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(5..6),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(6..7),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(7..8),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(8..9),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(9..10),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+    }
+
+    #[test]
+    fn parse_hex_brace() {
+        assert_eq!(
+            parser(r"\u{26c4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(
+                    ast::HexLiteralKind::UnicodeShort),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\U{26c4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(
+                    ast::HexLiteralKind::UnicodeLong),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\x{26c4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\x{26C4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\x{10fFfF}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..10),
+                kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                c: '\u{10FFFF}',
+            })));
+
+        assert_eq!(
+            parser(r"\x").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\x{").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\x{FF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..5),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\x{}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..4),
+                kind: ast::ErrorKind::EscapeHexEmpty,
+            });
+        assert_eq!(
+            parser(r"\x{FGF}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\x{FFFFFF}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..9),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+        assert_eq!(
+            parser(r"\x{D800}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..7),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+        assert_eq!(
+            parser(r"\x{FFFFFFFFF}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..12),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+    }
+
+    #[test]
+    fn parse_decimal() {
+        assert_eq!(parser("123").parse_decimal(), Ok(123));
+        assert_eq!(parser("0").parse_decimal(), Ok(0));
+        assert_eq!(parser("01").parse_decimal(), Ok(1));
+
+        assert_eq!(
+            parser("-1").parse_decimal().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser("").parse_decimal().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser("9999999999").parse_decimal().unwrap_err(),
+            TestError {
+                span: span(0..10),
+                kind: ast::ErrorKind::DecimalInvalid,
+            });
+    }
+
+    #[test]
+    fn parse_set_class() {
+        fn union(span: Span, items: Vec<ast::ClassSetItem>) -> ast::ClassSet {
+            ast::ClassSet::union(ast::ClassSetUnion {
+                span: span,
+                items: items,
+            })
+        }
+
+        fn intersection(
+            span: Span,
+            lhs: ast::ClassSet,
+            rhs: ast::ClassSet,
+        ) -> ast::ClassSet {
+            ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+                span: span,
+                kind: ast::ClassSetBinaryOpKind::Intersection,
+                lhs: Box::new(lhs),
+                rhs: Box::new(rhs),
+            })
+        }
+
+        fn difference(
+            span: Span,
+            lhs: ast::ClassSet,
+            rhs: ast::ClassSet,
+        ) -> ast::ClassSet {
+            ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+                span: span,
+                kind: ast::ClassSetBinaryOpKind::Difference,
+                lhs: Box::new(lhs),
+                rhs: Box::new(rhs),
+            })
+        }
+
+        fn symdifference(
+            span: Span,
+            lhs: ast::ClassSet,
+            rhs: ast::ClassSet,
+        ) -> ast::ClassSet {
+            ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+                span: span,
+                kind: ast::ClassSetBinaryOpKind::SymmetricDifference,
+                lhs: Box::new(lhs),
+                rhs: Box::new(rhs),
+            })
+        }
+
+        fn itemset(item: ast::ClassSetItem) -> ast::ClassSet {
+            ast::ClassSet::Item(item)
+        }
+
+        fn item_ascii(cls: ast::ClassAscii) -> ast::ClassSetItem {
+            ast::ClassSetItem::Ascii(cls)
+        }
+
+        fn item_unicode(cls: ast::ClassUnicode) -> ast::ClassSetItem {
+            ast::ClassSetItem::Unicode(cls)
+        }
+
+        fn item_perl(cls: ast::ClassPerl) -> ast::ClassSetItem {
+            ast::ClassSetItem::Perl(cls)
+        }
+
+        fn item_bracket(cls: ast::ClassBracketed) -> ast::ClassSetItem {
+            ast::ClassSetItem::Bracketed(Box::new(cls))
+        }
+
+        fn lit(span: Span, c: char) -> ast::ClassSetItem {
+            ast::ClassSetItem::Literal(ast::Literal {
+                span: span,
+                kind: ast::LiteralKind::Verbatim,
+                c: c,
+            })
+        }
+
+        fn empty(span: Span) -> ast::ClassSetItem {
+            ast::ClassSetItem::Empty(span)
+        }
+
+        fn range(span: Span, start: char, end: char) -> ast::ClassSetItem {
+            let pos1 = Position {
+                offset: span.start.offset + start.len_utf8(),
+                column: span.start.column + 1,
+                ..span.start
+            };
+            let pos2 = Position {
+                offset: span.end.offset - end.len_utf8(),
+                column: span.end.column - 1,
+                ..span.end
+            };
+            ast::ClassSetItem::Range(ast::ClassSetRange {
+                span: span,
+                start: ast::Literal {
+                    span: Span { end: pos1, ..span },
+                    kind: ast::LiteralKind::Verbatim,
+                    c: start,
+                },
+                end: ast::Literal {
+                    span: Span { start: pos2, ..span },
+                    kind: ast::LiteralKind::Verbatim,
+                    c: end,
+                },
+            })
+        }
+
+        fn alnum(span: Span, negated: bool) -> ast::ClassAscii {
+            ast::ClassAscii {
+                span: span,
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: negated,
+            }
+        }
+
+        fn lower(span: Span, negated: bool) -> ast::ClassAscii {
+            ast::ClassAscii {
+                span: span,
+                kind: ast::ClassAsciiKind::Lower,
+                negated: negated,
+            }
+        }
+
+        assert_eq!(
+            parser("[[:alnum:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..11),
+                negated: false,
+                kind: itemset(item_ascii(alnum(span(1..10), false))),
+            }))));
+        assert_eq!(
+            parser("[[[:alnum:]]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..13),
+                negated: false,
+                kind: itemset(item_bracket(ast::ClassBracketed {
+                    span: span(1..12),
+                    negated: false,
+                    kind: itemset(item_ascii(alnum(span(2..11), false))),
+                })),
+            }))));
+        assert_eq!(
+            parser("[[:alnum:]&&[:lower:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..22),
+                negated: false,
+                kind: intersection(
+                    span(1..21),
+                    itemset(item_ascii(alnum(span(1..10), false))),
+                    itemset(item_ascii(lower(span(12..21), false))),
+                ),
+            }))));
+        assert_eq!(
+            parser("[[:alnum:]--[:lower:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..22),
+                negated: false,
+                kind: difference(
+                    span(1..21),
+                    itemset(item_ascii(alnum(span(1..10), false))),
+                    itemset(item_ascii(lower(span(12..21), false))),
+                ),
+            }))));
+        assert_eq!(
+            parser("[[:alnum:]~~[:lower:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..22),
+                negated: false,
+                kind: symdifference(
+                    span(1..21),
+                    itemset(item_ascii(alnum(span(1..10), false))),
+                    itemset(item_ascii(lower(span(12..21), false))),
+                ),
+            }))));
+
+        assert_eq!(
+            parser("[a]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..3),
+                negated: false,
+                kind: itemset(lit(span(1..2), 'a')),
+            }))));
+        assert_eq!(
+            parser(r"[a\]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: union(span(1..4), vec![
+                    lit(span(1..2), 'a'),
+                    ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(2..4),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: ']',
+                    }),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[a\-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..6),
+                negated: false,
+                kind: union(span(1..5), vec![
+                    lit(span(1..2), 'a'),
+                    ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(2..4),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '-',
+                    }),
+                    lit(span(4..5), 'z'),
+                ]),
+            }))));
+        assert_eq!(
+            parser("[ab]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: union(span(1..3), vec![
+                    lit(span(1..2), 'a'),
+                    lit(span(2..3), 'b'),
+                ]),
+            }))));
+        assert_eq!(
+            parser("[a-]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: union(span(1..3), vec![
+                    lit(span(1..2), 'a'),
+                    lit(span(2..3), '-'),
+                ]),
+            }))));
+        assert_eq!(
+            parser("[-a]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: union(span(1..3), vec![
+                    lit(span(1..2), '-'),
+                    lit(span(2..3), 'a'),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[\pL]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: itemset(item_unicode(ast::ClassUnicode {
+                    span: span(1..4),
+                    negated: false,
+                    kind: ast::ClassUnicodeKind::OneLetter('L'),
+                })),
+            }))));
+        assert_eq!(
+            parser(r"[\w]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: itemset(item_perl(ast::ClassPerl {
+                    span: span(1..3),
+                    kind: ast::ClassPerlKind::Word,
+                    negated: false,
+                })),
+            }))));
+        assert_eq!(
+            parser(r"[a\wz]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..6),
+                negated: false,
+                kind: union(span(1..5), vec![
+                    lit(span(1..2), 'a'),
+                    item_perl(ast::ClassPerl {
+                        span: span(2..4),
+                        kind: ast::ClassPerlKind::Word,
+                        negated: false,
+                    }),
+                    lit(span(4..5), 'z'),
+                ]),
+            }))));
+
+        assert_eq!(
+            parser("[a-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: itemset(range(span(1..4), 'a', 'z')),
+            }))));
+        assert_eq!(
+            parser("[a-cx-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..8),
+                negated: false,
+                kind: union(span(1..7), vec![
+                    range(span(1..4), 'a', 'c'),
+                    range(span(4..7), 'x', 'z'),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[\w&&a-cx-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..12),
+                negated: false,
+                kind: intersection(
+                    span(1..11),
+                    itemset(item_perl(ast::ClassPerl {
+                        span: span(1..3),
+                        kind: ast::ClassPerlKind::Word,
+                        negated: false,
+                    })),
+                    union(span(5..11), vec![
+                        range(span(5..8), 'a', 'c'),
+                        range(span(8..11), 'x', 'z'),
+                    ]),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[a-cx-z&&\w]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..12),
+                negated: false,
+                kind: intersection(
+                    span(1..11),
+                    union(span(1..7), vec![
+                        range(span(1..4), 'a', 'c'),
+                        range(span(4..7), 'x', 'z'),
+                    ]),
+                    itemset(item_perl(ast::ClassPerl {
+                        span: span(9..11),
+                        kind: ast::ClassPerlKind::Word,
+                        negated: false,
+                    })),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[a--b--c]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..9),
+                negated: false,
+                kind: difference(
+                    span(1..8),
+                    difference(
+                        span(1..5),
+                        itemset(lit(span(1..2), 'a')),
+                        itemset(lit(span(4..5), 'b')),
+                    ),
+                    itemset(lit(span(7..8), 'c')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[a~~b~~c]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..9),
+                negated: false,
+                kind: symdifference(
+                    span(1..8),
+                    symdifference(
+                        span(1..5),
+                        itemset(lit(span(1..2), 'a')),
+                        itemset(lit(span(4..5), 'b')),
+                    ),
+                    itemset(lit(span(7..8), 'c')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[\^&&^]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..7),
+                negated: false,
+                kind: intersection(
+                    span(1..6),
+                    itemset(ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(1..3),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '^',
+                    })),
+                    itemset(lit(span(5..6), '^')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[\&&&&]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..7),
+                negated: false,
+                kind: intersection(
+                    span(1..6),
+                    itemset(ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(1..3),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '&',
+                    })),
+                    itemset(lit(span(5..6), '&')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[&&&&]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..6),
+                negated: false,
+                kind: intersection(
+                    span(1..5),
+                    intersection(
+                        span(1..3),
+                        itemset(empty(span(1..1))),
+                        itemset(empty(span(3..3))),
+                    ),
+                    itemset(empty(span(5..5))),
+                ),
+            }))));
+
+        let pat = "[☃-⛄]";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span_range(pat, 0..9),
+                negated: false,
+                kind: itemset(ast::ClassSetItem::Range(ast::ClassSetRange {
+                    span: span_range(pat, 1..8),
+                    start: ast::Literal {
+                        span: span_range(pat, 1..4),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '☃',
+                    },
+                    end: ast::Literal {
+                        span: span_range(pat, 5..8),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '⛄',
+                    },
+                })),
+            }))));
+
+        assert_eq!(
+            parser(r"[]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..3),
+                negated: false,
+                kind: itemset(lit(span(1..2), ']')),
+            }))));
+        assert_eq!(
+            parser(r"[]\[]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: union(span(1..4), vec![
+                    lit(span(1..2), ']'),
+                    ast::ClassSetItem::Literal(ast::Literal  {
+                        span: span(2..4),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '[',
+                    }),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[\[]]").parse(),
+            Ok(concat(0..5, vec![
+                Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: itemset(ast::ClassSetItem::Literal(ast::Literal  {
+                        span: span(1..3),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '[',
+                    })),
+                })),
+                Ast::Literal(ast::Literal {
+                    span: span(4..5),
+                    kind: ast::LiteralKind::Verbatim,
+                    c: ']',
+                }),
+            ])));
+
+        assert_eq!(
+            parser("[").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[[").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[[-]").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[[[:alnum:]").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser(r"[\b]").parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::ClassEscapeInvalid,
+            });
+        assert_eq!(
+            parser(r"[\w-a]").parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::ClassRangeLiteral,
+            });
+        assert_eq!(
+            parser(r"[a-\w]").parse().unwrap_err(),
+            TestError {
+                span: span(3..5),
+                kind: ast::ErrorKind::ClassRangeLiteral,
+            });
+        assert_eq!(
+            parser(r"[z-a]").parse().unwrap_err(),
+            TestError {
+                span: span(1..4),
+                kind: ast::ErrorKind::ClassRangeInvalid,
+            });
+
+        assert_eq!(
+            parser_ignore_whitespace("[a ").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[a- ").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+    }
+
+    #[test]
+    fn parse_set_class_open() {
+        assert_eq!(
+            parser("[a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..1),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..1),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[   a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(4..4),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(4..4),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[^a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..2),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[ ^ a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(4..4),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(4..4),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[-a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..2),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[ - a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[^-a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..3),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[--a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..3),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[]a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..2),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: ']',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[ ] a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: ']',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[^]a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..3),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: ']',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[-]a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..2),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+
+        assert_eq!(
+            parser("[").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[    ")
+            .parse_set_class_open()
+            .unwrap_err(),
+            TestError {
+                span: span(0..5),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[^").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[]").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[-").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[--").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+    }
+
+    #[test]
+    fn maybe_parse_ascii_class() {
+        assert_eq!(
+            parser(r"[:alnum:]").maybe_parse_ascii_class(),
+            Some(ast::ClassAscii {
+                span: span(0..9),
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: false,
+            }));
+        assert_eq!(
+            parser(r"[:alnum:]A").maybe_parse_ascii_class(),
+            Some(ast::ClassAscii {
+                span: span(0..9),
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: false,
+            }));
+        assert_eq!(
+            parser(r"[:^alnum:]").maybe_parse_ascii_class(),
+            Some(ast::ClassAscii {
+                span: span(0..10),
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: true,
+            }));
+
+        let p = parser(r"[:");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:^");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[^:alnum:]");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:alnnum:]");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:alnum]");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:alnum:");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+    }
+
+    #[test]
+    fn parse_unicode_class() {
+        assert_eq!(
+            parser(r"\pN").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..3),
+                negated: false,
+                kind: ast::ClassUnicodeKind::OneLetter('N'),
+            })));
+        assert_eq!(
+            parser(r"\PN").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..3),
+                negated: true,
+                kind: ast::ClassUnicodeKind::OneLetter('N'),
+            })));
+        assert_eq!(
+            parser(r"\p{N}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: false,
+                kind: ast::ClassUnicodeKind::Named(s("N")),
+            })));
+        assert_eq!(
+            parser(r"\P{N}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: true,
+                kind: ast::ClassUnicodeKind::Named(s("N")),
+            })));
+        assert_eq!(
+            parser(r"\p{Greek}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..9),
+                negated: false,
+                kind: ast::ClassUnicodeKind::Named(s("Greek")),
+            })));
+
+        assert_eq!(
+            parser(r"\p{scx:Katakana}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..16),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Colon,
+                    name: s("scx"),
+                    value: s("Katakana"),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{scx=Katakana}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..16),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Equal,
+                    name: s("scx"),
+                    value: s("Katakana"),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{scx!=Katakana}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..17),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::NotEqual,
+                    name: s("scx"),
+                    value: s("Katakana"),
+                },
+            })));
+
+        assert_eq!(
+            parser(r"\p{:}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Colon,
+                    name: s(""),
+                    value: s(""),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{=}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Equal,
+                    name: s(""),
+                    value: s(""),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{!=}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..6),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::NotEqual,
+                    name: s(""),
+                    value: s(""),
+                },
+            })));
+
+        assert_eq!(
+            parser(r"\p").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\p{").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\p{N").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\p{Greek").parse_escape().unwrap_err(),
+            TestError {
+                span: span(8..8),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+
+        assert_eq!(
+            parser(r"\pNz").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..4),
+                asts: vec![
+                    Ast::Class(ast::Class::Unicode(ast::ClassUnicode {
+                        span: span(0..3),
+                        negated: false,
+                        kind: ast::ClassUnicodeKind::OneLetter('N'),
+                    })),
+                    Ast::Literal(ast::Literal {
+                        span: span(3..4),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'z',
+                    }),
+                ],
+            })));
+        assert_eq!(
+            parser(r"\p{Greek}z").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..10),
+                asts: vec![
+                    Ast::Class(ast::Class::Unicode(ast::ClassUnicode {
+                        span: span(0..9),
+                        negated: false,
+                        kind: ast::ClassUnicodeKind::Named(s("Greek")),
+                    })),
+                    Ast::Literal(ast::Literal {
+                        span: span(9..10),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'z',
+                    }),
+                ],
+            })));
+    }
+
+    #[test]
+    fn parse_perl_class() {
+        assert_eq!(
+            parser(r"\d").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Digit,
+                negated: false,
+            })));
+        assert_eq!(
+            parser(r"\D").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Digit,
+                negated: true,
+            })));
+        assert_eq!(
+            parser(r"\s").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Space,
+                negated: false,
+            })));
+        assert_eq!(
+            parser(r"\S").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Space,
+                negated: true,
+            })));
+        assert_eq!(
+            parser(r"\w").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Word,
+                negated: false,
+            })));
+        assert_eq!(
+            parser(r"\W").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Word,
+                negated: true,
+            })));
+
+        assert_eq!(
+            parser(r"\d").parse(),
+            Ok(Ast::Class(ast::Class::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Digit,
+                negated: false,
+            }))));
+        assert_eq!(
+            parser(r"\dz").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..3),
+                asts: vec![
+                    Ast::Class(ast::Class::Perl(ast::ClassPerl {
+                        span: span(0..2),
+                        kind: ast::ClassPerlKind::Digit,
+                        negated: false,
+                    })),
+                    Ast::Literal(ast::Literal {
+                        span: span(2..3),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'z',
+                    }),
+                ],
+            })));
+    }
+
+    // This tests a bug fix where the nest limit checker wasn't decrementing
+    // its depth during post-traversal, which causes long regexes to trip
+    // the default limit too aggressively.
+    #[test]
+    fn regression_454_nest_too_big() {
+        let pattern = r#"
+        2(?:
+          [45]\d{3}|
+          7(?:
+            1[0-267]|
+            2[0-289]|
+            3[0-29]|
+            4[01]|
+            5[1-3]|
+            6[013]|
+            7[0178]|
+            91
+          )|
+          8(?:
+            0[125]|
+            [139][1-6]|
+            2[0157-9]|
+            41|
+            6[1-35]|
+            7[1-5]|
+            8[1-8]|
+            90
+          )|
+          9(?:
+            0[0-2]|
+            1[0-4]|
+            2[568]|
+            3[3-6]|
+            5[5-7]|
+            6[0167]|
+            7[15]|
+            8[0146-9]
+          )
+        )\d{4}
+        "#;
+        assert!(parser_nest_limit(pattern, 50).parse().is_ok());
+    }
+
+    // This tests that we treat a trailing `-` in a character class as a
+    // literal `-` even when whitespace mode is enabled and there is whitespace
+    // after the trailing `-`.
+    #[test]
+    fn regression_455_trailing_dash_ignore_whitespace() {
+        assert!(parser("(?x)[ / - ]").parse().is_ok());
+        assert!(parser("(?x)[ a - ]").parse().is_ok());
+        assert!(parser("(?x)[
+            a
+            - ]
+        ").parse().is_ok());
+        assert!(parser("(?x)[
+            a # wat
+            - ]
+        ").parse().is_ok());
+
+        assert!(parser("(?x)[ / -").parse().is_err());
+        assert!(parser("(?x)[ / - ").parse().is_err());
+        assert!(parser("(?x)[
+            / -
+        ").parse().is_err());
+        assert!(parser("(?x)[
+            / - # wat
+        ").parse().is_err());
+    }
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/ast/print.rs b/rustc_deps/vendor/regex-syntax/src/ast/print.rs
new file mode 100644
index 0000000..4441b4d
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/ast/print.rs
@@ -0,0 +1,586 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+This module provides a regular expression printer for `Ast`.
+*/
+
+use std::fmt;
+
+use ast::{self, Ast};
+use ast::visitor::{self, Visitor};
+
+/// A builder for constructing a printer.
+///
+/// Note that since a printer doesn't have any configuration knobs, this type
+/// remains unexported.
+#[derive(Clone, Debug)]
+struct PrinterBuilder {
+    _priv: (),
+}
+
+impl Default for PrinterBuilder {
+    fn default() -> PrinterBuilder {
+        PrinterBuilder::new()
+    }
+}
+
+impl PrinterBuilder {
+    fn new() -> PrinterBuilder {
+        PrinterBuilder {
+            _priv: (),
+        }
+    }
+
+    fn build(&self) -> Printer {
+        Printer {
+            _priv: (),
+        }
+    }
+}
+
+/// A printer for a regular expression abstract syntax tree.
+///
+/// A printer converts an abstract syntax tree (AST) to a regular expression
+/// pattern string. This particular printer uses constant stack space and heap
+/// space proportional to the size of the AST.
+///
+/// This printer will not necessarily preserve the original formatting of the
+/// regular expression pattern string. For example, all whitespace and comments
+/// are ignored.
+#[derive(Debug)]
+pub struct Printer {
+    _priv: (),
+}
+
+impl Printer {
+    /// Create a new printer.
+    pub fn new() -> Printer {
+        PrinterBuilder::new().build()
+    }
+
+    /// Print the given `Ast` to the given writer. The writer must implement
+    /// `fmt::Write`. Typical implementations of `fmt::Write` that can be used
+    /// here are a `fmt::Formatter` (which is available in `fmt::Display`
+    /// implementations) or a `&mut String`.
+    pub fn print<W: fmt::Write>(&mut self, ast: &Ast, wtr: W) -> fmt::Result {
+        visitor::visit(ast, Writer { printer: self, wtr: wtr })
+    }
+}
+
+#[derive(Debug)]
+struct Writer<'p, W> {
+    printer: &'p mut Printer,
+    wtr: W,
+}
+
+impl<'p, W: fmt::Write> Visitor for Writer<'p, W> {
+    type Output = ();
+    type Err = fmt::Error;
+
+    fn finish(self) -> fmt::Result {
+        Ok(())
+    }
+
+    fn visit_pre(&mut self, ast: &Ast) -> fmt::Result {
+        match *ast {
+            Ast::Group(ref x) => self.fmt_group_pre(x),
+            Ast::Class(ast::Class::Bracketed(ref x)) => {
+                self.fmt_class_bracketed_pre(x)
+            }
+            _ => Ok(())
+        }
+    }
+
+    fn visit_post(&mut self, ast: &Ast) -> fmt::Result {
+        use ast::Class;
+
+        match *ast {
+            Ast::Empty(_) => Ok(()),
+            Ast::Flags(ref x) => self.fmt_set_flags(x),
+            Ast::Literal(ref x) => self.fmt_literal(x),
+            Ast::Dot(_) => self.wtr.write_str("."),
+            Ast::Assertion(ref x) => self.fmt_assertion(x),
+            Ast::Class(Class::Perl(ref x)) => self.fmt_class_perl(x),
+            Ast::Class(Class::Unicode(ref x)) => self.fmt_class_unicode(x),
+            Ast::Class(Class::Bracketed(ref x)) => {
+                self.fmt_class_bracketed_post(x)
+            }
+            Ast::Repetition(ref x) => self.fmt_repetition(x),
+            Ast::Group(ref x) => self.fmt_group_post(x),
+            Ast::Alternation(_) => Ok(()),
+            Ast::Concat(_) => Ok(()),
+        }
+    }
+
+    fn visit_alternation_in(&mut self) -> fmt::Result {
+        self.wtr.write_str("|")
+    }
+
+    fn visit_class_set_item_pre(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        match *ast {
+            ast::ClassSetItem::Bracketed(ref x) => {
+                self.fmt_class_bracketed_pre(x)
+            }
+            _ => Ok(()),
+        }
+    }
+
+    fn visit_class_set_item_post(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        use ast::ClassSetItem::*;
+
+        match *ast {
+            Empty(_) => Ok(()),
+            Literal(ref x) => self.fmt_literal(x),
+            Range(ref x) => {
+                self.fmt_literal(&x.start)?;
+                self.wtr.write_str("-")?;
+                self.fmt_literal(&x.end)?;
+                Ok(())
+            }
+            Ascii(ref x) => self.fmt_class_ascii(x),
+            Unicode(ref x) => self.fmt_class_unicode(x),
+            Perl(ref x) => self.fmt_class_perl(x),
+            Bracketed(ref x) => self.fmt_class_bracketed_post(x),
+            Union(_) => Ok(()),
+        }
+    }
+
+    fn visit_class_set_binary_op_in(
+        &mut self,
+        ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        self.fmt_class_set_binary_op_kind(&ast.kind)
+    }
+}
+
+impl<'p, W: fmt::Write> Writer<'p, W> {
+    fn fmt_group_pre(&mut self, ast: &ast::Group) -> fmt::Result {
+        use ast::GroupKind::*;
+        match ast.kind {
+            CaptureIndex(_) => self.wtr.write_str("("),
+            CaptureName(ref x) => {
+                self.wtr.write_str("(?P<")?;
+                self.wtr.write_str(&x.name)?;
+                self.wtr.write_str(">")?;
+                Ok(())
+            }
+            NonCapturing(ref flags) => {
+                self.wtr.write_str("(?")?;
+                self.fmt_flags(flags)?;
+                self.wtr.write_str(":")?;
+                Ok(())
+            }
+        }
+    }
+
+    fn fmt_group_post(&mut self, _ast: &ast::Group) -> fmt::Result {
+        self.wtr.write_str(")")
+    }
+
+    fn fmt_repetition(&mut self, ast: &ast::Repetition) -> fmt::Result {
+        use ast::RepetitionKind::*;
+        match ast.op.kind {
+            ZeroOrOne if ast.greedy => self.wtr.write_str("?"),
+            ZeroOrOne => self.wtr.write_str("??"),
+            ZeroOrMore if ast.greedy => self.wtr.write_str("*"),
+            ZeroOrMore => self.wtr.write_str("*?"),
+            OneOrMore if ast.greedy => self.wtr.write_str("+"),
+            OneOrMore => self.wtr.write_str("+?"),
+            Range(ref x) => {
+                self.fmt_repetition_range(x)?;
+                if !ast.greedy {
+                    self.wtr.write_str("?")?;
+                }
+                Ok(())
+            }
+        }
+    }
+
+    fn fmt_repetition_range(
+        &mut self,
+        ast: &ast::RepetitionRange,
+    ) -> fmt::Result {
+        use ast::RepetitionRange::*;
+        match *ast {
+            Exactly(x) => write!(self.wtr, "{{{}}}", x),
+            AtLeast(x) => write!(self.wtr, "{{{},}}", x),
+            Bounded(x, y) => write!(self.wtr, "{{{},{}}}", x, y),
+        }
+    }
+
+    fn fmt_literal(&mut self, ast: &ast::Literal) -> fmt::Result {
+        use ast::LiteralKind::*;
+
+        match ast.kind {
+            Verbatim => self.wtr.write_char(ast.c),
+            Punctuation => write!(self.wtr, r"\{}", ast.c),
+            Octal => write!(self.wtr, r"\{:o}", ast.c as u32),
+            HexFixed(ast::HexLiteralKind::X) => {
+                write!(self.wtr, r"\x{:02X}", ast.c as u32)
+            }
+            HexFixed(ast::HexLiteralKind::UnicodeShort) => {
+                write!(self.wtr, r"\u{:04X}", ast.c as u32)
+            }
+            HexFixed(ast::HexLiteralKind::UnicodeLong) => {
+                write!(self.wtr, r"\U{:08X}", ast.c as u32)
+            }
+            HexBrace(ast::HexLiteralKind::X) => {
+                write!(self.wtr, r"\x{{{:X}}}", ast.c as u32)
+            }
+            HexBrace(ast::HexLiteralKind::UnicodeShort) => {
+                write!(self.wtr, r"\u{{{:X}}}", ast.c as u32)
+            }
+            HexBrace(ast::HexLiteralKind::UnicodeLong) => {
+                write!(self.wtr, r"\U{{{:X}}}", ast.c as u32)
+            }
+            Special(ast::SpecialLiteralKind::Bell) => {
+                self.wtr.write_str(r"\a")
+            }
+            Special(ast::SpecialLiteralKind::FormFeed) => {
+                self.wtr.write_str(r"\f")
+            }
+            Special(ast::SpecialLiteralKind::Tab) => {
+                self.wtr.write_str(r"\t")
+            }
+            Special(ast::SpecialLiteralKind::LineFeed) => {
+                self.wtr.write_str(r"\n")
+            }
+            Special(ast::SpecialLiteralKind::CarriageReturn) => {
+                self.wtr.write_str(r"\r")
+            }
+            Special(ast::SpecialLiteralKind::VerticalTab) => {
+                self.wtr.write_str(r"\v")
+            }
+            Special(ast::SpecialLiteralKind::Space) => {
+                self.wtr.write_str(r"\ ")
+            }
+        }
+    }
+
+    fn fmt_assertion(&mut self, ast: &ast::Assertion) -> fmt::Result {
+        use ast::AssertionKind::*;
+        match ast.kind {
+            StartLine => self.wtr.write_str("^"),
+            EndLine => self.wtr.write_str("$"),
+            StartText => self.wtr.write_str(r"\A"),
+            EndText => self.wtr.write_str(r"\z"),
+            WordBoundary => self.wtr.write_str(r"\b"),
+            NotWordBoundary => self.wtr.write_str(r"\B"),
+        }
+    }
+
+    fn fmt_set_flags(&mut self, ast: &ast::SetFlags) -> fmt::Result {
+        self.wtr.write_str("(?")?;
+        self.fmt_flags(&ast.flags)?;
+        self.wtr.write_str(")")?;
+        Ok(())
+    }
+
+    fn fmt_flags(&mut self, ast: &ast::Flags) -> fmt::Result {
+        use ast::{Flag, FlagsItemKind};
+
+        for item in &ast.items {
+            match item.kind {
+                FlagsItemKind::Negation => self.wtr.write_str("-"),
+                FlagsItemKind::Flag(ref flag) => {
+                    match *flag {
+                        Flag::CaseInsensitive => self.wtr.write_str("i"),
+                        Flag::MultiLine => self.wtr.write_str("m"),
+                        Flag::DotMatchesNewLine => self.wtr.write_str("s"),
+                        Flag::SwapGreed => self.wtr.write_str("U"),
+                        Flag::Unicode => self.wtr.write_str("u"),
+                        Flag::IgnoreWhitespace => self.wtr.write_str("x"),
+                    }
+                }
+            }?;
+        }
+        Ok(())
+    }
+
+    fn fmt_class_bracketed_pre(
+        &mut self,
+        ast: &ast::ClassBracketed,
+    ) -> fmt::Result {
+        if ast.negated {
+            self.wtr.write_str("[^")
+        } else {
+            self.wtr.write_str("[")
+        }
+    }
+
+    fn fmt_class_bracketed_post(
+        &mut self,
+        _ast: &ast::ClassBracketed,
+    ) -> fmt::Result {
+        self.wtr.write_str("]")
+    }
+
+    fn fmt_class_set_binary_op_kind(
+        &mut self,
+        ast: &ast::ClassSetBinaryOpKind,
+    ) -> fmt::Result {
+        use ast::ClassSetBinaryOpKind::*;
+        match *ast {
+            Intersection => self.wtr.write_str("&&"),
+            Difference => self.wtr.write_str("--"),
+            SymmetricDifference => self.wtr.write_str("~~"),
+        }
+    }
+
+    fn fmt_class_perl(&mut self, ast: &ast::ClassPerl) -> fmt::Result {
+        use ast::ClassPerlKind::*;
+        match ast.kind {
+            Digit if ast.negated => self.wtr.write_str(r"\D"),
+            Digit => self.wtr.write_str(r"\d"),
+            Space if ast.negated => self.wtr.write_str(r"\S"),
+            Space => self.wtr.write_str(r"\s"),
+            Word if ast.negated => self.wtr.write_str(r"\W"),
+            Word => self.wtr.write_str(r"\w"),
+        }
+    }
+
+    fn fmt_class_ascii(&mut self, ast: &ast::ClassAscii) -> fmt::Result {
+        use ast::ClassAsciiKind::*;
+        match ast.kind {
+            Alnum if ast.negated => self.wtr.write_str("[:^alnum:]"),
+            Alnum => self.wtr.write_str("[:alnum:]"),
+            Alpha if ast.negated => self.wtr.write_str("[:^alpha:]"),
+            Alpha => self.wtr.write_str("[:alpha:]"),
+            Ascii if ast.negated => self.wtr.write_str("[:^ascii:]"),
+            Ascii => self.wtr.write_str("[:ascii:]"),
+            Blank if ast.negated => self.wtr.write_str("[:^blank:]"),
+            Blank => self.wtr.write_str("[:blank:]"),
+            Cntrl if ast.negated => self.wtr.write_str("[:^cntrl:]"),
+            Cntrl => self.wtr.write_str("[:cntrl:]"),
+            Digit if ast.negated => self.wtr.write_str("[:^digit:]"),
+            Digit => self.wtr.write_str("[:digit:]"),
+            Graph if ast.negated => self.wtr.write_str("[:^graph:]"),
+            Graph => self.wtr.write_str("[:graph:]"),
+            Lower if ast.negated => self.wtr.write_str("[:^lower:]"),
+            Lower => self.wtr.write_str("[:lower:]"),
+            Print if ast.negated => self.wtr.write_str("[:^print:]"),
+            Print => self.wtr.write_str("[:print:]"),
+            Punct if ast.negated => self.wtr.write_str("[:^punct:]"),
+            Punct => self.wtr.write_str("[:punct:]"),
+            Space if ast.negated => self.wtr.write_str("[:^space:]"),
+            Space => self.wtr.write_str("[:space:]"),
+            Upper if ast.negated => self.wtr.write_str("[:^upper:]"),
+            Upper => self.wtr.write_str("[:upper:]"),
+            Word if ast.negated => self.wtr.write_str("[:^word:]"),
+            Word => self.wtr.write_str("[:word:]"),
+            Xdigit if ast.negated => self.wtr.write_str("[:^xdigit:]"),
+            Xdigit => self.wtr.write_str("[:xdigit:]"),
+        }
+    }
+
+    fn fmt_class_unicode(&mut self, ast: &ast::ClassUnicode) -> fmt::Result {
+        use ast::ClassUnicodeKind::*;
+        use ast::ClassUnicodeOpKind::*;
+
+        if ast.negated {
+            self.wtr.write_str(r"\P")?;
+        } else {
+            self.wtr.write_str(r"\p")?;
+        }
+        match ast.kind {
+            OneLetter(c) => self.wtr.write_char(c),
+            Named(ref x) => write!(self.wtr, "{{{}}}", x),
+            NamedValue { op: Equal, ref name, ref value } => {
+                write!(self.wtr, "{{{}={}}}", name, value)
+            }
+            NamedValue { op: Colon, ref name, ref value } => {
+                write!(self.wtr, "{{{}:{}}}", name, value)
+            }
+            NamedValue { op: NotEqual, ref name, ref value } => {
+                write!(self.wtr, "{{{}!={}}}", name, value)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ast::parse::ParserBuilder;
+    use super::Printer;
+
+    fn roundtrip(given: &str) {
+        roundtrip_with(|b| b, given);
+    }
+
+    fn roundtrip_with<F>(mut f: F, given: &str)
+    where F: FnMut(&mut ParserBuilder) -> &mut ParserBuilder
+    {
+        let mut builder = ParserBuilder::new();
+        f(&mut builder);
+        let ast = builder.build().parse(given).unwrap();
+
+        let mut printer = Printer::new();
+        let mut dst = String::new();
+        printer.print(&ast, &mut dst).unwrap();
+        assert_eq!(given, dst);
+    }
+
+    #[test]
+    fn print_literal() {
+        roundtrip("a");
+        roundtrip(r"\[");
+        roundtrip_with(|b| b.octal(true), r"\141");
+        roundtrip(r"\x61");
+        roundtrip(r"\x7F");
+        roundtrip(r"\u0061");
+        roundtrip(r"\U00000061");
+        roundtrip(r"\x{61}");
+        roundtrip(r"\x{7F}");
+        roundtrip(r"\u{61}");
+        roundtrip(r"\U{61}");
+
+        roundtrip(r"\a");
+        roundtrip(r"\f");
+        roundtrip(r"\t");
+        roundtrip(r"\n");
+        roundtrip(r"\r");
+        roundtrip(r"\v");
+        roundtrip(r"(?x)\ ");
+    }
+
+    #[test]
+    fn print_dot() {
+        roundtrip(".");
+    }
+
+    #[test]
+    fn print_concat() {
+        roundtrip("ab");
+        roundtrip("abcde");
+        roundtrip("a(bcd)ef");
+    }
+
+    #[test]
+    fn print_alternation() {
+        roundtrip("a|b");
+        roundtrip("a|b|c|d|e");
+        roundtrip("|a|b|c|d|e");
+        roundtrip("|a|b|c|d|e|");
+        roundtrip("a(b|c|d)|e|f");
+    }
+
+    #[test]
+    fn print_assertion() {
+        roundtrip(r"^");
+        roundtrip(r"$");
+        roundtrip(r"\A");
+        roundtrip(r"\z");
+        roundtrip(r"\b");
+        roundtrip(r"\B");
+    }
+
+    #[test]
+    fn print_repetition() {
+        roundtrip("a?");
+        roundtrip("a??");
+        roundtrip("a*");
+        roundtrip("a*?");
+        roundtrip("a+");
+        roundtrip("a+?");
+        roundtrip("a{5}");
+        roundtrip("a{5}?");
+        roundtrip("a{5,}");
+        roundtrip("a{5,}?");
+        roundtrip("a{5,10}");
+        roundtrip("a{5,10}?");
+    }
+
+    #[test]
+    fn print_flags() {
+        roundtrip("(?i)");
+        roundtrip("(?-i)");
+        roundtrip("(?s-i)");
+        roundtrip("(?-si)");
+        roundtrip("(?siUmux)");
+    }
+
+    #[test]
+    fn print_group() {
+        roundtrip("(?i:a)");
+        roundtrip("(?P<foo>a)");
+        roundtrip("(a)");
+    }
+
+    #[test]
+    fn print_class() {
+        roundtrip(r"[abc]");
+        roundtrip(r"[a-z]");
+        roundtrip(r"[^a-z]");
+        roundtrip(r"[a-z0-9]");
+        roundtrip(r"[-a-z0-9]");
+        roundtrip(r"[-a-z0-9]");
+        roundtrip(r"[a-z0-9---]");
+        roundtrip(r"[a-z&&m-n]");
+        roundtrip(r"[[a-z&&m-n]]");
+        roundtrip(r"[a-z--m-n]");
+        roundtrip(r"[a-z~~m-n]");
+        roundtrip(r"[a-z[0-9]]");
+        roundtrip(r"[a-z[^0-9]]");
+
+        roundtrip(r"\d");
+        roundtrip(r"\D");
+        roundtrip(r"\s");
+        roundtrip(r"\S");
+        roundtrip(r"\w");
+        roundtrip(r"\W");
+
+        roundtrip(r"[[:alnum:]]");
+        roundtrip(r"[[:^alnum:]]");
+        roundtrip(r"[[:alpha:]]");
+        roundtrip(r"[[:^alpha:]]");
+        roundtrip(r"[[:ascii:]]");
+        roundtrip(r"[[:^ascii:]]");
+        roundtrip(r"[[:blank:]]");
+        roundtrip(r"[[:^blank:]]");
+        roundtrip(r"[[:cntrl:]]");
+        roundtrip(r"[[:^cntrl:]]");
+        roundtrip(r"[[:digit:]]");
+        roundtrip(r"[[:^digit:]]");
+        roundtrip(r"[[:graph:]]");
+        roundtrip(r"[[:^graph:]]");
+        roundtrip(r"[[:lower:]]");
+        roundtrip(r"[[:^lower:]]");
+        roundtrip(r"[[:print:]]");
+        roundtrip(r"[[:^print:]]");
+        roundtrip(r"[[:punct:]]");
+        roundtrip(r"[[:^punct:]]");
+        roundtrip(r"[[:space:]]");
+        roundtrip(r"[[:^space:]]");
+        roundtrip(r"[[:upper:]]");
+        roundtrip(r"[[:^upper:]]");
+        roundtrip(r"[[:word:]]");
+        roundtrip(r"[[:^word:]]");
+        roundtrip(r"[[:xdigit:]]");
+        roundtrip(r"[[:^xdigit:]]");
+
+        roundtrip(r"\pL");
+        roundtrip(r"\PL");
+        roundtrip(r"\p{L}");
+        roundtrip(r"\P{L}");
+        roundtrip(r"\p{X=Y}");
+        roundtrip(r"\P{X=Y}");
+        roundtrip(r"\p{X:Y}");
+        roundtrip(r"\P{X:Y}");
+        roundtrip(r"\p{X!=Y}");
+        roundtrip(r"\P{X!=Y}");
+    }
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/ast/visitor.rs b/rustc_deps/vendor/regex-syntax/src/ast/visitor.rs
new file mode 100644
index 0000000..9b93a1a
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/ast/visitor.rs
@@ -0,0 +1,557 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+
+use ast::{self, Ast};
+
+/// A trait for visiting an abstract syntax tree (AST) in depth first order.
+///
+/// The principle aim of this trait is to enable callers to perform case
+/// analysis on an abstract syntax tree without necessarily using recursion.
+/// In particular, this permits callers to do case analysis with constant stack
+/// usage, which can be important since the size of an abstract syntax tree
+/// may be proportional to end user input.
+///
+/// Typical usage of this trait involves providing an implementation and then
+/// running it using the [`visit`](fn.visit.html) function.
+///
+/// Note that the abstract syntax tree for a regular expression is quite
+/// complex. Unless you specifically need it, you might be able to use the
+/// much simpler
+/// [high-level intermediate representation](../hir/struct.Hir.html)
+/// and its
+/// [corresponding `Visitor` trait](../hir/trait.Visitor.html)
+/// instead.
+pub trait Visitor {
+    /// The result of visiting an AST.
+    type Output;
+    /// An error that visiting an AST might return.
+    type Err;
+
+    /// All implementors of `Visitor` must provide a `finish` method, which
+    /// yields the result of visiting the AST or an error.
+    fn finish(self) -> Result<Self::Output, Self::Err>;
+
+    /// This method is called before beginning traversal of the AST.
+    fn start(&mut self) {}
+
+    /// This method is called on an `Ast` before descending into child `Ast`
+    /// nodes.
+    fn visit_pre(&mut self, _ast: &Ast) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on an `Ast` after descending all of its child
+    /// `Ast` nodes.
+    fn visit_post(&mut self, _ast: &Ast) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called between child nodes of an
+    /// [`Alternation`](struct.Alternation.html).
+    fn visit_alternation_in(&mut self) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetItem`](enum.ClassSetItem.html)
+    /// before descending into child nodes.
+    fn visit_class_set_item_pre(
+        &mut self,
+        _ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetItem`](enum.ClassSetItem.html)
+    /// after descending into child nodes.
+    fn visit_class_set_item_post(
+        &mut self,
+        _ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetBinaryOp`](struct.ClassSetBinaryOp.html)
+    /// before descending into child nodes.
+    fn visit_class_set_binary_op_pre(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetBinaryOp`](struct.ClassSetBinaryOp.html)
+    /// after descending into child nodes.
+    fn visit_class_set_binary_op_post(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called between the left hand and right hand child nodes
+    /// of a [`ClassSetBinaryOp`](struct.ClassSetBinaryOp.html).
+    fn visit_class_set_binary_op_in(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+}
+
+/// Executes an implementation of `Visitor` in constant stack space.
+///
+/// This function will visit every node in the given `Ast` while calling the
+/// appropriate methods provided by the
+/// [`Visitor`](trait.Visitor.html) trait.
+///
+/// The primary use case for this method is when one wants to perform case
+/// analysis over an `Ast` without using a stack size proportional to the depth
+/// of the `Ast`. Namely, this method will instead use constant stack size, but
+/// will use heap space proportional to the size of the `Ast`. This may be
+/// desirable in cases where the size of `Ast` is proportional to end user
+/// input.
+///
+/// If the visitor returns an error at any point, then visiting is stopped and
+/// the error is returned.
+pub fn visit<V: Visitor>(ast: &Ast, visitor: V) -> Result<V::Output, V::Err> {
+    HeapVisitor::new().visit(ast, visitor)
+}
+
+/// HeapVisitor visits every item in an `Ast` recursively using constant stack
+/// size and a heap size proportional to the size of the `Ast`.
+struct HeapVisitor<'a> {
+    /// A stack of `Ast` nodes. This is roughly analogous to the call stack
+    /// used in a typical recursive visitor.
+    stack: Vec<(&'a Ast, Frame<'a>)>,
+    /// Similar to the `Ast` stack above, but is used only for character
+    /// classes. In particular, character classes embed their own mini
+    /// recursive syntax.
+    stack_class: Vec<(ClassInduct<'a>, ClassFrame<'a>)>,
+}
+
+/// Represents a single stack frame while performing structural induction over
+/// an `Ast`.
+enum Frame<'a> {
+    /// A stack frame allocated just before descending into a repetition
+    /// operator's child node.
+    Repetition(&'a ast::Repetition),
+    /// A stack frame allocated just before descending into a group's child
+    /// node.
+    Group(&'a ast::Group),
+    /// The stack frame used while visiting every child node of a concatenation
+    /// of expressions.
+    Concat {
+        /// The child node we are currently visiting.
+        head: &'a Ast,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [Ast],
+    },
+    /// The stack frame used while visiting every child node of an alternation
+    /// of expressions.
+    Alternation {
+        /// The child node we are currently visiting.
+        head: &'a Ast,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [Ast],
+    },
+}
+
+/// Represents a single stack frame while performing structural induction over
+/// a character class.
+enum ClassFrame<'a> {
+    /// The stack frame used while visiting every child node of a union of
+    /// character class items.
+    Union {
+        /// The child node we are currently visiting.
+        head: &'a ast::ClassSetItem,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [ast::ClassSetItem],
+    },
+    /// The stack frame used while a binary class operation.
+    Binary {
+        op: &'a ast::ClassSetBinaryOp,
+    },
+    /// A stack frame allocated just before descending into a binary operator's
+    /// left hand child node.
+    BinaryLHS {
+        op: &'a ast::ClassSetBinaryOp,
+        lhs: &'a ast::ClassSet,
+        rhs: &'a ast::ClassSet,
+    },
+    /// A stack frame allocated just before descending into a binary operator's
+    /// right hand child node.
+    BinaryRHS {
+        op: &'a ast::ClassSetBinaryOp,
+        rhs: &'a ast::ClassSet,
+    },
+}
+
+/// A representation of the inductive step when performing structural induction
+/// over a character class.
+///
+/// Note that there is no analogous explicit type for the inductive step for
+/// `Ast` nodes because the inductive step is just an `Ast`. For character
+/// classes, the inductive step can produce one of two possible child nodes:
+/// an item or a binary operation. (An item cannot be a binary operation
+/// because that would imply binary operations can be unioned in the concrete
+/// syntax, which is not possible.)
+enum ClassInduct<'a> {
+    Item(&'a ast::ClassSetItem),
+    BinaryOp(&'a ast::ClassSetBinaryOp),
+}
+
+impl<'a> HeapVisitor<'a> {
+    fn new() -> HeapVisitor<'a> {
+        HeapVisitor { stack: vec![], stack_class: vec![] }
+    }
+
+    fn visit<V: Visitor>(
+        &mut self,
+        mut ast: &'a Ast,
+        mut visitor: V,
+    ) -> Result<V::Output, V::Err> {
+        self.stack.clear();
+        self.stack_class.clear();
+
+        visitor.start();
+        loop {
+            visitor.visit_pre(ast)?;
+            if let Some(x) = self.induct(ast, &mut visitor)? {
+                let child = x.child();
+                self.stack.push((ast, x));
+                ast = child;
+                continue;
+            }
+            // No induction means we have a base case, so we can post visit
+            // it now.
+            visitor.visit_post(ast)?;
+
+            // At this point, we now try to pop our call stack until it is
+            // either empty or we hit another inductive case.
+            loop {
+                let (post_ast, frame) = match self.stack.pop() {
+                    None => return visitor.finish(),
+                    Some((post_ast, frame)) => (post_ast, frame),
+                };
+                // If this is a concat/alternate, then we might have additional
+                // inductive steps to process.
+                if let Some(x) = self.pop(frame) {
+                    if let Frame::Alternation {..} = x {
+                        visitor.visit_alternation_in()?;
+                    }
+                    ast = x.child();
+                    self.stack.push((post_ast, x));
+                    break;
+                }
+                // Otherwise, we've finished visiting all the child nodes for
+                // this AST, so we can post visit it now.
+                visitor.visit_post(post_ast)?;
+            }
+        }
+    }
+
+    /// Build a stack frame for the given AST if one is needed (which occurs if
+    /// and only if there are child nodes in the AST). Otherwise, return None.
+    ///
+    /// If this visits a class, then the underlying visitor implementation may
+    /// return an error which will be passed on here.
+    fn induct<V: Visitor>(
+        &mut self,
+        ast: &'a Ast,
+        visitor: &mut V,
+    ) -> Result<Option<Frame<'a>>, V::Err> {
+        Ok(match *ast {
+            Ast::Class(ast::Class::Bracketed(ref x)) => {
+                self.visit_class(x, visitor)?;
+                None
+            }
+            Ast::Repetition(ref x) => Some(Frame::Repetition(x)),
+            Ast::Group(ref x) => Some(Frame::Group(x)),
+            Ast::Concat(ref x) if x.asts.is_empty() => None,
+            Ast::Concat(ref x) => {
+                Some(Frame::Concat {
+                    head: &x.asts[0],
+                    tail: &x.asts[1..],
+                })
+            }
+            Ast::Alternation(ref x) if x.asts.is_empty() => None,
+            Ast::Alternation(ref x) => {
+                Some(Frame::Alternation {
+                    head: &x.asts[0],
+                    tail: &x.asts[1..],
+                })
+            }
+            _ => None,
+        })
+    }
+
+    /// Pops the given frame. If the frame has an additional inductive step,
+    /// then return it, otherwise return `None`.
+    fn pop(&self, induct: Frame<'a>) -> Option<Frame<'a>> {
+        match induct {
+            Frame::Repetition(_) => None,
+            Frame::Group(_) => None,
+            Frame::Concat { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(Frame::Concat {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+            Frame::Alternation { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(Frame::Alternation {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+        }
+    }
+
+    fn visit_class<V: Visitor>(
+        &mut self,
+        ast: &'a ast::ClassBracketed,
+        visitor: &mut V,
+    ) -> Result<(), V::Err> {
+        let mut ast = ClassInduct::from_bracketed(ast);
+        loop {
+            self.visit_class_pre(&ast, visitor)?;
+            if let Some(x) = self.induct_class(&ast) {
+                let child = x.child();
+                self.stack_class.push((ast, x));
+                ast = child;
+                continue;
+            }
+            self.visit_class_post(&ast, visitor)?;
+
+            // At this point, we now try to pop our call stack until it is
+            // either empty or we hit another inductive case.
+            loop {
+                let (post_ast, frame) = match self.stack_class.pop() {
+                    None => return Ok(()),
+                    Some((post_ast, frame)) => (post_ast, frame),
+                };
+                // If this is a union or a binary op, then we might have
+                // additional inductive steps to process.
+                if let Some(x) = self.pop_class(frame) {
+                    if let ClassFrame::BinaryRHS { ref op, .. } = x {
+                        visitor.visit_class_set_binary_op_in(op)?;
+                    }
+                    ast = x.child();
+                    self.stack_class.push((post_ast, x));
+                    break;
+                }
+                // Otherwise, we've finished visiting all the child nodes for
+                // this class node, so we can post visit it now.
+                self.visit_class_post(&post_ast, visitor)?;
+            }
+        }
+    }
+
+    /// Call the appropriate `Visitor` methods given an inductive step.
+    fn visit_class_pre<V: Visitor>(
+        &self,
+        ast: &ClassInduct<'a>,
+        visitor: &mut V,
+    ) -> Result<(), V::Err> {
+        match *ast {
+            ClassInduct::Item(item) => {
+                visitor.visit_class_set_item_pre(item)?;
+            }
+            ClassInduct::BinaryOp(op) => {
+                visitor.visit_class_set_binary_op_pre(op)?;
+            }
+        }
+        Ok(())
+    }
+
+    /// Call the appropriate `Visitor` methods given an inductive step.
+    fn visit_class_post<V: Visitor>(
+        &self,
+        ast: &ClassInduct<'a>,
+        visitor: &mut V,
+    ) -> Result<(), V::Err> {
+        match *ast {
+            ClassInduct::Item(item) => {
+                visitor.visit_class_set_item_post(item)?;
+            }
+            ClassInduct::BinaryOp(op) => {
+                visitor.visit_class_set_binary_op_post(op)?;
+            }
+        }
+        Ok(())
+    }
+
+    /// Build a stack frame for the given class node if one is needed (which
+    /// occurs if and only if there are child nodes). Otherwise, return None.
+    fn induct_class(
+        &self,
+        ast: &ClassInduct<'a>,
+    ) -> Option<ClassFrame<'a>> {
+        match *ast {
+            ClassInduct::Item(&ast::ClassSetItem::Bracketed(ref x)) => {
+                match x.kind {
+                    ast::ClassSet::Item(ref item) => {
+                        Some(ClassFrame::Union {
+                            head: item,
+                            tail: &[],
+                        })
+                    }
+                    ast::ClassSet::BinaryOp(ref op) => {
+                        Some(ClassFrame::Binary { op: op })
+                    }
+                }
+            }
+            ClassInduct::Item(&ast::ClassSetItem::Union(ref x)) => {
+                if x.items.is_empty() {
+                    None
+                } else {
+                    Some(ClassFrame::Union {
+                        head: &x.items[0],
+                        tail: &x.items[1..],
+                    })
+                }
+            }
+            ClassInduct::BinaryOp(op) => {
+                Some(ClassFrame::BinaryLHS {
+                    op: op,
+                    lhs: &op.lhs,
+                    rhs: &op.rhs,
+                })
+            }
+            _ => None,
+        }
+    }
+
+    /// Pops the given frame. If the frame has an additional inductive step,
+    /// then return it, otherwise return `None`.
+    fn pop_class(&self, induct: ClassFrame<'a>) -> Option<ClassFrame<'a>> {
+        match induct {
+            ClassFrame::Union { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(ClassFrame::Union {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+            ClassFrame::Binary {..} => None,
+            ClassFrame::BinaryLHS { op, rhs, .. } => {
+                Some(ClassFrame::BinaryRHS {
+                    op: op,
+                    rhs: rhs,
+                })
+            }
+            ClassFrame::BinaryRHS {..} => None,
+        }
+    }
+}
+
+impl<'a> Frame<'a> {
+    /// Perform the next inductive step on this frame and return the next
+    /// child AST node to visit.
+    fn child(&self) -> &'a Ast {
+        match *self {
+            Frame::Repetition(rep) => &rep.ast,
+            Frame::Group(group) => &group.ast,
+            Frame::Concat { head, .. } => head,
+            Frame::Alternation { head, .. } => head,
+        }
+    }
+}
+
+impl<'a> ClassFrame<'a> {
+    /// Perform the next inductive step on this frame and return the next
+    /// child class node to visit.
+    fn child(&self) -> ClassInduct<'a> {
+        match *self {
+            ClassFrame::Union { head, .. } => ClassInduct::Item(head),
+            ClassFrame::Binary { op, .. } => ClassInduct::BinaryOp(op),
+            ClassFrame::BinaryLHS { ref lhs, .. } => {
+                ClassInduct::from_set(lhs)
+            }
+            ClassFrame::BinaryRHS { ref rhs, .. } => {
+                ClassInduct::from_set(rhs)
+            }
+        }
+    }
+}
+
+impl<'a> ClassInduct<'a> {
+    fn from_bracketed(ast: &'a ast::ClassBracketed) -> ClassInduct<'a> {
+        ClassInduct::from_set(&ast.kind)
+    }
+
+    fn from_set(ast: &'a ast::ClassSet) -> ClassInduct<'a> {
+        match *ast {
+            ast::ClassSet::Item(ref item) => ClassInduct::Item(item),
+            ast::ClassSet::BinaryOp(ref op) => ClassInduct::BinaryOp(op),
+        }
+    }
+}
+
+impl<'a> fmt::Debug for ClassFrame<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let x = match *self {
+            ClassFrame::Union{..} => "Union",
+            ClassFrame::Binary{..} => "Binary",
+            ClassFrame::BinaryLHS{..} => "BinaryLHS",
+            ClassFrame::BinaryRHS{..} => "BinaryRHS",
+        };
+        write!(f, "{}", x)
+    }
+}
+
+impl<'a> fmt::Debug for ClassInduct<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let x = match *self {
+            ClassInduct::Item(it) => {
+                match *it {
+                    ast::ClassSetItem::Empty(_) => "Item(Empty)",
+                    ast::ClassSetItem::Literal(_) => "Item(Literal)",
+                    ast::ClassSetItem::Range(_) => "Item(Range)",
+                    ast::ClassSetItem::Ascii(_) => "Item(Ascii)",
+                    ast::ClassSetItem::Perl(_) => "Item(Perl)",
+                    ast::ClassSetItem::Unicode(_) => "Item(Unicode)",
+                    ast::ClassSetItem::Bracketed(_) => "Item(Bracketed)",
+                    ast::ClassSetItem::Union(_) => "Item(Union)",
+                }
+            }
+            ClassInduct::BinaryOp(it) => {
+                match it.kind {
+                    ast::ClassSetBinaryOpKind::Intersection => {
+                        "BinaryOp(Intersection)"
+                    }
+                    ast::ClassSetBinaryOpKind::Difference => {
+                        "BinaryOp(Difference)"
+                    }
+                    ast::ClassSetBinaryOpKind::SymmetricDifference => {
+                        "BinaryOp(SymmetricDifference)"
+                    }
+                }
+            }
+        };
+        write!(f, "{}", x)
+    }
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/either.rs b/rustc_deps/vendor/regex-syntax/src/either.rs
new file mode 100644
index 0000000..7ae41e4
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/either.rs
@@ -0,0 +1,8 @@
+/// A simple binary sum type.
+///
+/// This is occasionally useful in an ad hoc fashion.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Either<Left, Right> {
+    Left(Left),
+    Right(Right),
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/error.rs b/rustc_deps/vendor/regex-syntax/src/error.rs
new file mode 100644
index 0000000..1f5b8f8
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/error.rs
@@ -0,0 +1,297 @@
+use std::cmp;
+use std::error;
+use std::fmt;
+use std::result;
+
+use ast;
+use hir;
+
+/// A type alias for dealing with errors returned by this crate.
+pub type Result<T> = result::Result<T, Error>;
+
+/// This error type encompasses any error that can be returned by this crate.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Error {
+    /// An error that occurred while translating concrete syntax into abstract
+    /// syntax (AST).
+    Parse(ast::Error),
+    /// An error that occurred while translating abstract syntax into a high
+    /// level intermediate representation (HIR).
+    Translate(hir::Error),
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl From<ast::Error> for Error {
+    fn from(err: ast::Error) -> Error {
+        Error::Parse(err)
+    }
+}
+
+impl From<hir::Error> for Error {
+    fn from(err: hir::Error) -> Error {
+        Error::Translate(err)
+    }
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        match *self {
+            Error::Parse(ref x) => x.description(),
+            Error::Translate(ref x) => x.description(),
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Parse(ref x) => x.fmt(f),
+            Error::Translate(ref x) => x.fmt(f),
+            _ => unreachable!(),
+        }
+    }
+}
+
+/// A helper type for formatting nice error messages.
+///
+/// This type is responsible for reporting regex parse errors in a nice human
+/// readable format. Most of its complexity is from interspersing notational
+/// markers pointing out the position where an error occurred.
+#[derive(Debug)]
+pub struct Formatter<'e, E: 'e> {
+    /// The original regex pattern in which the error occurred.
+    pattern: &'e str,
+    /// The error kind. It must impl fmt::Display.
+    err: &'e E,
+    /// The primary span of the error.
+    span: &'e ast::Span,
+    /// An auxiliary and optional span, in case the error needs to point to
+    /// two locations (e.g., when reporting a duplicate capture group name).
+    aux_span: Option<&'e ast::Span>,
+}
+
+impl<'e> From<&'e ast::Error> for Formatter<'e, ast::ErrorKind> {
+    fn from(err: &'e ast::Error) -> Self {
+        Formatter {
+            pattern: err.pattern(),
+            err: err.kind(),
+            span: err.span(),
+            aux_span: err.auxiliary_span(),
+        }
+    }
+}
+
+impl<'e> From<&'e hir::Error> for Formatter<'e, hir::ErrorKind> {
+    fn from(err: &'e hir::Error) -> Self {
+        Formatter {
+            pattern: err.pattern(),
+            err: err.kind(),
+            span: err.span(),
+            aux_span: None,
+        }
+    }
+}
+
+impl<'e, E: fmt::Display> fmt::Display for Formatter<'e, E> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let spans = Spans::from_formatter(self);
+        if self.pattern.contains('\n') {
+            let divider = repeat_char('~', 79);
+
+            writeln!(f, "regex parse error:")?;
+            writeln!(f, "{}", divider)?;
+            let notated = spans.notate();
+            write!(f, "{}", notated)?;
+            writeln!(f, "{}", divider)?;
+            // If we have error spans that cover multiple lines, then we just
+            // note the line numbers.
+            if !spans.multi_line.is_empty() {
+                let mut notes = vec![];
+                for span in &spans.multi_line {
+                    notes.push(format!(
+                        "on line {} (column {}) through line {} (column {})",
+                        span.start.line, span.start.column,
+                        span.end.line, span.end.column - 1));
+                }
+                writeln!(f, "{}", notes.join("\n"))?;
+            }
+            write!(f, "error: {}", self.err)?;
+        } else {
+            writeln!(f, "regex parse error:")?;
+            let notated = Spans::from_formatter(self).notate();
+            write!(f, "{}", notated)?;
+            write!(f, "error: {}", self.err)?;
+        }
+        Ok(())
+    }
+}
+
+/// This type represents an arbitrary number of error spans in a way that makes
+/// it convenient to notate the regex pattern. ("Notate" means "point out
+/// exactly where the error occurred in the regex pattern.")
+///
+/// Technically, we can only ever have two spans given our current error
+/// structure. However, after toiling with a specific algorithm for handling
+/// two spans, it became obvious that an algorithm to handle an arbitrary
+/// number of spans was actually much simpler.
+struct Spans<'p> {
+    /// The original regex pattern string.
+    pattern: &'p str,
+    /// The total width that should be used for line numbers. The width is
+    /// used for left padding the line numbers for alignment.
+    ///
+    /// A value of `0` means line numbers should not be displayed. That is,
+    /// the pattern is itself only one line.
+    line_number_width: usize,
+    /// All error spans that occur on a single line. This sequence always has
+    /// length equivalent to the number of lines in `pattern`, where the index
+    /// of the sequence represents a line number, starting at `0`. The spans
+    /// in each line are sorted in ascending order.
+    by_line: Vec<Vec<ast::Span>>,
+    /// All error spans that occur over one or more lines. That is, the start
+    /// and end position of the span have different line numbers. The spans are
+    /// sorted in ascending order.
+    multi_line: Vec<ast::Span>,
+}
+
+impl<'p> Spans<'p> {
+    /// Build a sequence of spans from a formatter.
+    fn from_formatter<'e, E: fmt::Display>(
+        fmter: &'p Formatter<'e, E>,
+    ) -> Spans<'p> {
+        let mut line_count = fmter.pattern.lines().count();
+        // If the pattern ends with a `\n` literal, then our line count is
+        // off by one, since a span can occur immediately after the last `\n`,
+        // which is consider to be an additional line.
+        if fmter.pattern.ends_with('\n') {
+            line_count += 1;
+        }
+        let line_number_width =
+            if line_count <= 1 {
+                0
+            } else {
+                line_count.to_string().len()
+            };
+        let mut spans = Spans {
+            pattern: &fmter.pattern,
+            line_number_width: line_number_width,
+            by_line: vec![vec![]; line_count],
+            multi_line: vec![],
+        };
+        spans.add(fmter.span.clone());
+        if let Some(span) = fmter.aux_span {
+            spans.add(span.clone());
+        }
+        spans
+    }
+
+    /// Add the given span to this sequence, putting it in the right place.
+    fn add(&mut self, span: ast::Span) {
+        // This is grossly inefficient since we sort after each add, but right
+        // now, we only ever add two spans at most.
+        if span.is_one_line() {
+            let i = span.start.line - 1; // because lines are 1-indexed
+            self.by_line[i].push(span);
+            self.by_line[i].sort();
+        } else {
+            self.multi_line.push(span);
+            self.multi_line.sort();
+        }
+    }
+
+    /// Notate the pattern string with carents (`^`) pointing at each span
+    /// location. This only applies to spans that occur within a single line.
+    fn notate(&self) -> String {
+        let mut notated = String::new();
+        for (i, line) in self.pattern.lines().enumerate() {
+            if self.line_number_width > 0 {
+                notated.push_str(&self.left_pad_line_number(i + 1));
+                notated.push_str(": ");
+            } else {
+                notated.push_str("    ");
+            }
+            notated.push_str(line);
+            notated.push('\n');
+            if let Some(notes) = self.notate_line(i) {
+                notated.push_str(&notes);
+                notated.push('\n');
+            }
+        }
+        notated
+    }
+
+    /// Return notes for the line indexed at `i` (zero-based). If there are no
+    /// spans for the given line, then `None` is returned. Otherwise, an
+    /// appropriately space padded string with correctly positioned `^` is
+    /// returned, accounting for line numbers.
+    fn notate_line(&self, i: usize) -> Option<String> {
+        let spans = &self.by_line[i];
+        if spans.is_empty() {
+            return None;
+        }
+        let mut notes = String::new();
+        for _ in 0..self.line_number_padding() {
+            notes.push(' ');
+        }
+        let mut pos = 0;
+        for span in spans {
+            for _ in pos..(span.start.column - 1) {
+                notes.push(' ');
+                pos += 1;
+            }
+            let note_len = span.end.column.saturating_sub(span.start.column);
+            for _ in 0..cmp::max(1, note_len) {
+                notes.push('^');
+                pos += 1;
+            }
+        }
+        Some(notes)
+    }
+
+    /// Left pad the given line number with spaces such that it is aligned with
+    /// other line numbers.
+    fn left_pad_line_number(&self, n: usize) -> String {
+        let n = n.to_string();
+        let pad = self.line_number_width.checked_sub(n.len()).unwrap();
+        let mut result = repeat_char(' ', pad);
+        result.push_str(&n);
+        result
+    }
+
+    /// Return the line number padding beginning at the start of each line of
+    /// the pattern.
+    ///
+    /// If the pattern is only one line, then this returns a fixed padding
+    /// for visual indentation.
+    fn line_number_padding(&self) -> usize {
+        if self.line_number_width == 0 {
+            4
+        } else {
+            2 + self.line_number_width
+        }
+    }
+}
+
+fn repeat_char(c: char, count: usize) -> String {
+    ::std::iter::repeat(c).take(count).collect()
+}
+
+#[cfg(test)]
+mod tests {
+    use ast::parse::Parser;
+
+    // See: https://github.com/rust-lang/regex/issues/464
+    #[test]
+    fn regression_464() {
+        let err = Parser::new().parse("a{\n").unwrap_err();
+        // This test checks that the error formatter doesn't panic.
+        assert!(!err.to_string().is_empty());
+    }
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/hir/interval.rs b/rustc_deps/vendor/regex-syntax/src/hir/interval.rs
new file mode 100644
index 0000000..a7e70ef
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/hir/interval.rs
@@ -0,0 +1,490 @@
+use std::char;
+use std::cmp;
+use std::fmt::Debug;
+use std::slice;
+use std::u8;
+
+// This module contains an *internal* implementation of interval sets.
+//
+// The primary invariant that interval sets guards is canonical ordering. That
+// is, every interval set contains an ordered sequence of intervals where
+// no two intervals are overlapping or adjacent. While this invariant is
+// ocassionally broken within the implementation, it should be impossible for
+// callers to observe it.
+//
+// Since case folding (as implemented below) breaks that invariant, we roll
+// that into this API even though it is a little out of place in an otherwise
+// generic interval set.
+//
+// Some of the implementation complexity here is a result of me wanting to
+// preserve the sequential representation without using additional memory.
+// In many cases, we do use linear extra memory, but it is at most 2x and it
+// is amortized. If we relaxed the memory requirements, this implementation
+// could become much simpler. The extra memory is honestly probably OK, but
+// character classes (especially of the Unicode variety) can become quite
+// large, and it would be nice to keep regex compilation snappy even in debug
+// builds. (In the past, I have been careless with this area of code and it has
+// caused slow regex compilations in debug mode, so this isn't entirely
+// unwarranted.)
+//
+// Tests on this are relegated to the public API of HIR in src/hir.rs.
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct IntervalSet<I> {
+    ranges: Vec<I>,
+}
+
+impl<I: Interval> IntervalSet<I> {
+    /// Create a new set from a sequence of intervals. Each interval is
+    /// specified as a pair of bounds, where both bounds are inclusive.
+    ///
+    /// The given ranges do not need to be in any specific order, and ranges
+    /// may overlap.
+    pub fn new<T: IntoIterator<Item=I>>(intervals: T) -> IntervalSet<I> {
+        let mut set = IntervalSet { ranges: intervals.into_iter().collect() };
+        set.canonicalize();
+        set
+    }
+
+    /// Add a new interval to this set.
+    pub fn push(&mut self, interval: I) {
+        // TODO: This could be faster. e.g., Push the interval such that
+        // it preserves canonicalization.
+        self.ranges.push(interval);
+        self.canonicalize();
+    }
+
+    /// Return an iterator over all intervals in this set.
+    ///
+    /// The iterator yields intervals in ascending order.
+    pub fn iter(&self) -> IntervalSetIter<I> {
+        IntervalSetIter(self.ranges.iter())
+    }
+
+    /// Return an immutable slice of intervals in this set.
+    ///
+    /// The sequence returned is in canonical ordering.
+    pub fn intervals(&self) -> &[I] {
+        &self.ranges
+    }
+
+    /// Expand this interval set such that it contains all case folded
+    /// characters. For example, if this class consists of the range `a-z`,
+    /// then applying case folding will result in the class containing both the
+    /// ranges `a-z` and `A-Z`.
+    pub fn case_fold_simple(&mut self) {
+        let len = self.ranges.len();
+        for i in 0..len {
+            let range = self.ranges[i];
+            range.case_fold_simple(&mut self.ranges);
+        }
+        self.canonicalize();
+    }
+
+    /// Union this set with the given set, in place.
+    pub fn union(&mut self, other: &IntervalSet<I>) {
+        // This could almost certainly be done more efficiently.
+        self.ranges.extend(&other.ranges);
+        self.canonicalize();
+    }
+
+    /// Intersect this set with the given set, in place.
+    pub fn intersect(&mut self, other: &IntervalSet<I>) {
+        if self.ranges.is_empty() {
+            return;
+        }
+        if other.ranges.is_empty() {
+            self.ranges.clear();
+            return;
+        }
+
+        // There should be a way to do this in-place with constant memory,
+        // but I couldn't figure out a simple way to do it. So just append
+        // the intersection to the end of this range, and then drain it before
+        // we're done.
+        let drain_end = self.ranges.len();
+
+        let mut ita = (0..drain_end).into_iter();
+        let mut itb = (0..other.ranges.len()).into_iter();
+        let mut a = ita.next().unwrap();
+        let mut b = itb.next().unwrap();
+        loop {
+            if let Some(ab) = self.ranges[a].intersect(&other.ranges[b]) {
+                self.ranges.push(ab);
+            }
+            let (it, aorb) =
+                if self.ranges[a].upper() < other.ranges[b].upper() {
+                    (&mut ita, &mut a)
+                } else {
+                    (&mut itb, &mut b)
+                };
+            match it.next() {
+                Some(v) => *aorb = v,
+                None => break,
+            }
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Subtract the given set from this set, in place.
+    pub fn difference(&mut self, other: &IntervalSet<I>) {
+        if self.ranges.is_empty() || other.ranges.is_empty() {
+            return;
+        }
+
+        // This algorithm is (to me) surprisingly complex. A search of the
+        // interwebs indicate that this is a potentially interesting problem.
+        // Folks seem to suggest interval or segment trees, but I'd like to
+        // avoid the overhead (both runtime and conceptual) of that.
+        //
+        // The following is basically my Shitty First Draft. Therefore, in
+        // order to grok it, you probably need to read each line carefully.
+        // Simplifications are most welcome!
+        //
+        // Remember, we can assume the canonical format invariant here, which
+        // says that all ranges are sorted, not overlapping and not adjacent in
+        // each class.
+        let drain_end = self.ranges.len();
+        let (mut a, mut b) = (0, 0);
+    'LOOP:
+        while a < drain_end && b < other.ranges.len() {
+            // Basically, the easy cases are when neither range overlaps with
+            // each other. If the `b` range is less than our current `a`
+            // range, then we can skip it and move on.
+            if other.ranges[b].upper() < self.ranges[a].lower() {
+                b += 1;
+                continue;
+            }
+            // ... similarly for the `a` range. If it's less than the smallest
+            // `b` range, then we can add it as-is.
+            if self.ranges[a].upper() < other.ranges[b].lower() {
+                let range = self.ranges[a];
+                self.ranges.push(range);
+                a += 1;
+                continue;
+            }
+            // Otherwise, we have overlapping ranges.
+            assert!(!self.ranges[a].is_intersection_empty(&other.ranges[b]));
+
+            // This part is tricky and was non-obvious to me without looking
+            // at explicit examples (see the tests). The trickiness stems from
+            // two things: 1) subtracting a range from another range could
+            // yield two ranges and 2) after subtracting a range, it's possible
+            // that future ranges can have an impact. The loop below advances
+            // the `b` ranges until they can't possible impact the current
+            // range.
+            //
+            // For example, if our `a` range is `a-t` and our next three `b`
+            // ranges are `a-c`, `g-i`, `r-t` and `x-z`, then we need to apply
+            // subtraction three times before moving on to the next `a` range.
+            let mut range = self.ranges[a];
+            while b < other.ranges.len()
+                && !range.is_intersection_empty(&other.ranges[b])
+            {
+                let old_range = range;
+                range = match range.difference(&other.ranges[b]) {
+                    (None, None) => {
+                        // We lost the entire range, so move on to the next
+                        // without adding this one.
+                        a += 1;
+                        continue 'LOOP;
+                    }
+                    (Some(range1), None) | (None, Some(range1)) => range1,
+                    (Some(range1), Some(range2)) => {
+                        self.ranges.push(range1);
+                        range2
+                    }
+                };
+                // It's possible that the `b` range has more to contribute
+                // here. In particular, if it is greater than the original
+                // range, then it might impact the next `a` range *and* it
+                // has impacted the current `a` range as much as possible,
+                // so we can quit. We don't bump `b` so that the next `a`
+                // range can apply it.
+                if other.ranges[b].upper() > old_range.upper() {
+                    break;
+                }
+                // Otherwise, the next `b` range might apply to the current
+                // `a` range.
+                b += 1;
+            }
+            self.ranges.push(range);
+            a += 1;
+        }
+        while a < drain_end {
+            let range = self.ranges[a];
+            self.ranges.push(range);
+            a += 1;
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Compute the symmetric difference of the two sets, in place.
+    ///
+    /// This computes the symmetric difference of two interval sets. This
+    /// removes all elements in this set that are also in the given set,
+    /// but also adds all elements from the given set that aren't in this
+    /// set. That is, the set will contain all elements in either set,
+    /// but will not contain any elements that are in both sets.
+    pub fn symmetric_difference(&mut self, other: &IntervalSet<I>) {
+        // TODO(burntsushi): Fix this so that it amortizes allocation.
+        let mut intersection = self.clone();
+        intersection.intersect(other);
+        self.union(other);
+        self.difference(&intersection);
+    }
+
+    /// Negate this interval set.
+    ///
+    /// For all `x` where `x` is any element, if `x` was in this set, then it
+    /// will not be in this set after negation.
+    pub fn negate(&mut self) {
+        if self.ranges.is_empty() {
+            let (min, max) = (I::Bound::min_value(), I::Bound::max_value());
+            self.ranges.push(I::create(min, max));
+            return;
+        }
+
+        // There should be a way to do this in-place with constant memory,
+        // but I couldn't figure out a simple way to do it. So just append
+        // the negation to the end of this range, and then drain it before
+        // we're done.
+        let drain_end = self.ranges.len();
+
+        // We do checked arithmetic below because of the canonical ordering
+        // invariant.
+        if self.ranges[0].lower() > I::Bound::min_value() {
+            let upper = self.ranges[0].lower().decrement();
+            self.ranges.push(I::create(I::Bound::min_value(), upper));
+        }
+        for i in 1..drain_end {
+            let lower = self.ranges[i - 1].upper().increment();
+            let upper = self.ranges[i].lower().decrement();
+            self.ranges.push(I::create(lower, upper));
+        }
+        if self.ranges[drain_end - 1].upper() < I::Bound::max_value() {
+            let lower = self.ranges[drain_end - 1].upper().increment();
+            self.ranges.push(I::create(lower, I::Bound::max_value()));
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Converts this set into a canonical ordering.
+    fn canonicalize(&mut self) {
+        if self.is_canonical() {
+            return;
+        }
+        self.ranges.sort();
+        assert!(!self.ranges.is_empty());
+
+        // Is there a way to do this in-place with constant memory? I couldn't
+        // figure out a way to do it. So just append the canonicalization to
+        // the end of this range, and then drain it before we're done.
+        let drain_end = self.ranges.len();
+        for oldi in 0..drain_end {
+            // If we've added at least one new range, then check if we can
+            // merge this range in the previously added range.
+            if self.ranges.len() > drain_end {
+                let (last, rest) = self.ranges.split_last_mut().unwrap();
+                if let Some(union) = last.union(&rest[oldi]) {
+                    *last = union;
+                    continue;
+                }
+            }
+            let range = self.ranges[oldi];
+            self.ranges.push(range);
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Returns true if and only if this class is in a canonical ordering.
+    fn is_canonical(&self) -> bool {
+        for pair in self.ranges.windows(2) {
+            if pair[0] >= pair[1] {
+                return false;
+            }
+            if pair[0].is_contiguous(&pair[1]) {
+                return false;
+            }
+        }
+        true
+    }
+}
+
+/// An iterator over intervals.
+#[derive(Debug)]
+pub struct IntervalSetIter<'a, I: 'a>(slice::Iter<'a, I>);
+
+impl<'a, I> Iterator for IntervalSetIter<'a, I> {
+    type Item = &'a I;
+
+    fn next(&mut self) -> Option<&'a I> {
+        self.0.next()
+    }
+}
+
+pub trait Interval:
+    Clone + Copy + Debug + Default + Eq + PartialEq + PartialOrd + Ord
+{
+    type Bound: Bound;
+
+    fn lower(&self) -> Self::Bound;
+    fn upper(&self) -> Self::Bound;
+    fn set_lower(&mut self, bound: Self::Bound);
+    fn set_upper(&mut self, bound: Self::Bound);
+    fn case_fold_simple(&self, intervals: &mut Vec<Self>);
+
+    /// Create a new interval.
+    fn create(lower: Self::Bound, upper: Self::Bound) -> Self {
+        let mut int = Self::default();
+        if lower <= upper {
+            int.set_lower(lower);
+            int.set_upper(upper);
+        } else {
+            int.set_lower(upper);
+            int.set_upper(lower);
+        }
+        int
+    }
+
+    /// Union the given overlapping range into this range.
+    ///
+    /// If the two ranges aren't contiguous, then this returns `None`.
+    fn union(&self, other: &Self) -> Option<Self> {
+        if !self.is_contiguous(other) {
+            return None;
+        }
+        let lower = cmp::min(self.lower(), other.lower());
+        let upper = cmp::max(self.upper(), other.upper());
+        Some(Self::create(lower, upper))
+    }
+
+    /// Intersect this range with the given range and return the result.
+    ///
+    /// If the intersection is empty, then this returns `None`.
+    fn intersect(&self, other: &Self) -> Option<Self> {
+        let lower = cmp::max(self.lower(), other.lower());
+        let upper = cmp::min(self.upper(), other.upper());
+        if lower <= upper {
+            Some(Self::create(lower, upper))
+        } else {
+            None
+        }
+    }
+
+    /// Subtract the given range from this range and return the resulting
+    /// ranges.
+    ///
+    /// If subtraction would result in an empty range, then no ranges are
+    /// returned.
+    fn difference(&self, other: &Self) -> (Option<Self>, Option<Self>) {
+        if self.is_subset(other) {
+            return (None, None);
+        }
+        if self.is_intersection_empty(other) {
+            return (Some(self.clone()), None);
+        }
+        let add_lower = other.lower() > self.lower();
+        let add_upper = other.upper() < self.upper();
+        // We know this because !self.is_subset(other) and the ranges have
+        // a non-empty intersection.
+        assert!(add_lower || add_upper);
+        let mut ret = (None, None);
+        if add_lower {
+            let upper = other.lower().decrement();
+            ret.0 = Some(Self::create(self.lower(), upper));
+        }
+        if add_upper {
+            let lower = other.upper().increment();
+            let range = Self::create(lower, self.upper());
+            if ret.0.is_none() {
+                ret.0 = Some(range);
+            } else {
+                ret.1 = Some(range);
+            }
+        }
+        ret
+    }
+
+    /// Compute the symmetric difference the given range from this range. This
+    /// returns the union of the two ranges minus its intersection.
+    fn symmetric_difference(
+        &self,
+        other: &Self,
+    ) -> (Option<Self>, Option<Self>) {
+        let union = match self.union(other) {
+            None => return (Some(self.clone()), Some(other.clone())),
+            Some(union) => union,
+        };
+        let intersection = match self.intersect(other) {
+            None => return (Some(self.clone()), Some(other.clone())),
+            Some(intersection) => intersection,
+        };
+        union.difference(&intersection)
+    }
+
+    /// Returns true if and only if the two ranges are contiguous. Two ranges
+    /// are contiguous if and only if the ranges are either overlapping or
+    /// adjacent.
+    fn is_contiguous(&self, other: &Self) -> bool {
+        let lower1 = self.lower().as_u32();
+        let upper1 = self.upper().as_u32();
+        let lower2 = other.lower().as_u32();
+        let upper2 = other.upper().as_u32();
+        cmp::max(lower1, lower2) <= cmp::min(upper1, upper2).saturating_add(1)
+    }
+
+    /// Returns true if and only if the intersection of this range and the
+    /// other range is empty.
+    fn is_intersection_empty(&self, other: &Self) -> bool {
+        let (lower1, upper1) = (self.lower(), self.upper());
+        let (lower2, upper2) = (other.lower(), other.upper());
+        cmp::max(lower1, lower2) > cmp::min(upper1, upper2)
+    }
+
+    /// Returns true if and only if this range is a subset of the other range.
+    fn is_subset(&self, other: &Self) -> bool {
+        let (lower1, upper1) = (self.lower(), self.upper());
+        let (lower2, upper2) = (other.lower(), other.upper());
+        (lower2 <= lower1 && lower1 <= upper2)
+        && (lower2 <= upper1 && upper1 <= upper2)
+    }
+}
+
+pub trait Bound: Copy + Clone + Debug + Eq + PartialEq + PartialOrd + Ord {
+    fn min_value() -> Self;
+    fn max_value() -> Self;
+    fn as_u32(self) -> u32;
+    fn increment(self) -> Self;
+    fn decrement(self) -> Self;
+}
+
+impl Bound for u8 {
+    fn min_value() -> Self { u8::MIN }
+    fn max_value() -> Self { u8::MAX }
+    fn as_u32(self) -> u32 { self as u32 }
+    fn increment(self) -> Self { self.checked_add(1).unwrap() }
+    fn decrement(self) -> Self { self.checked_sub(1).unwrap() }
+}
+
+impl Bound for char {
+    fn min_value() -> Self { '\x00' }
+    fn max_value() -> Self { '\u{10FFFF}' }
+    fn as_u32(self) -> u32 { self as u32 }
+
+    fn increment(self) -> Self {
+        match self {
+            '\u{D7FF}' => '\u{E000}',
+            c => char::from_u32((c as u32).checked_add(1).unwrap()).unwrap(),
+        }
+    }
+
+    fn decrement(self) -> Self {
+        match self {
+            '\u{E000}' => '\u{D7FF}',
+            c => char::from_u32((c as u32).checked_sub(1).unwrap()).unwrap(),
+        }
+    }
+}
+
+// Tests for interval sets are written in src/hir.rs against the public API.
diff --git a/rustc_deps/vendor/regex-syntax/src/hir/literal/mod.rs b/rustc_deps/vendor/regex-syntax/src/hir/literal/mod.rs
new file mode 100644
index 0000000..b7d9c1d
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/hir/literal/mod.rs
@@ -0,0 +1,1551 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Provides routines for extracting literal prefixes and suffixes from an `Hir`.
+*/
+
+use std::cmp;
+use std::fmt;
+use std::iter;
+use std::mem;
+use std::ops;
+
+use hir::{self, Hir, HirKind};
+
+/// A set of literal byte strings extracted from a regular expression.
+///
+/// Every member of the set is a `Literal`, which is represented by a
+/// `Vec<u8>`. (Notably, it may contain invalid UTF-8.) Every member is
+/// said to be either *complete* or *cut*. A complete literal means that
+/// it extends until the beginning (or end) of the regular expression. In
+/// some circumstances, this can be used to indicate a match in the regular
+/// expression.
+///
+/// A key aspect of literal extraction is knowing when to stop. It is not
+/// feasible to blindly extract all literals from a regular expression, even if
+/// there are finitely many. For example, the regular expression `[0-9]{10}`
+/// has `10^10` distinct literals. For this reason, literal extraction is
+/// bounded to some low number by default using heuristics, but the limits can
+/// be tweaked.
+///
+/// **WARNING**: Literal extraction uses stack space proportional to the size
+/// of the `Hir` expression. At some point, this drawback will be eliminated.
+/// To protect yourself, set a reasonable
+/// [`nest_limit` on your `Parser`](../../struct.ParserBuilder.html#method.nest_limit).
+/// This is done for you by default.
+#[derive(Clone, Eq, PartialEq)]
+pub struct Literals {
+    lits: Vec<Literal>,
+    limit_size: usize,
+    limit_class: usize,
+}
+
+/// A single member of a set of literals extracted from a regular expression.
+///
+/// This type has `Deref` and `DerefMut` impls to `Vec<u8>` so that all slice
+/// and `Vec` operations are available.
+#[derive(Clone, Eq, Ord)]
+pub struct Literal {
+    v: Vec<u8>,
+    cut: bool,
+}
+
+impl Literals {
+    /// Returns a new empty set of literals using default limits.
+    pub fn empty() -> Literals {
+        Literals {
+            lits: vec![],
+            limit_size: 250,
+            limit_class: 10,
+        }
+    }
+
+    /// Returns a set of literal prefixes extracted from the given `Hir`.
+    pub fn prefixes(expr: &Hir) -> Literals {
+        let mut lits = Literals::empty();
+        lits.union_prefixes(expr);
+        lits
+    }
+
+    /// Returns a set of literal suffixes extracted from the given `Hir`.
+    pub fn suffixes(expr: &Hir) -> Literals {
+        let mut lits = Literals::empty();
+        lits.union_suffixes(expr);
+        lits
+    }
+
+    /// Get the approximate size limit (in bytes) of this set.
+    pub fn limit_size(&self) -> usize {
+        self.limit_size
+    }
+
+    /// Set the approximate size limit (in bytes) of this set.
+    ///
+    /// If extracting a literal would put the set over this limit, then
+    /// extraction stops.
+    ///
+    /// The new limits will only apply to additions to this set. Existing
+    /// members remain unchanged, even if the set exceeds the new limit.
+    pub fn set_limit_size(&mut self, size: usize) -> &mut Literals {
+        self.limit_size = size;
+        self
+    }
+
+    /// Get the character class size limit for this set.
+    pub fn limit_class(&self) -> usize {
+        self.limit_class
+    }
+
+    /// Limits the size of character(or byte) classes considered.
+    ///
+    /// A value of `0` prevents all character classes from being considered.
+    ///
+    /// This limit also applies to case insensitive literals, since each
+    /// character in the case insensitive literal is converted to a class, and
+    /// then case folded.
+    ///
+    /// The new limits will only apply to additions to this set. Existing
+    /// members remain unchanged, even if the set exceeds the new limit.
+    pub fn set_limit_class(&mut self, size: usize) -> &mut Literals {
+        self.limit_class = size;
+        self
+    }
+
+    /// Returns the set of literals as a slice. Its order is unspecified.
+    pub fn literals(&self) -> &[Literal] {
+        &self.lits
+    }
+
+    /// Returns the length of the smallest literal.
+    ///
+    /// Returns None is there are no literals in the set.
+    pub fn min_len(&self) -> Option<usize> {
+        let mut min = None;
+        for lit in &self.lits {
+            match min {
+                None => min = Some(lit.len()),
+                Some(m) if lit.len() < m => min = Some(lit.len()),
+                _ => {}
+            }
+        }
+        min
+    }
+
+    /// Returns true if all members in this set are complete.
+    pub fn all_complete(&self) -> bool {
+        !self.lits.is_empty() && self.lits.iter().all(|l| !l.is_cut())
+    }
+
+    /// Returns true if any member in this set is complete.
+    pub fn any_complete(&self) -> bool {
+        self.lits.iter().any(|lit| !lit.is_cut())
+    }
+
+    /// Returns true if this set contains an empty literal.
+    pub fn contains_empty(&self) -> bool {
+        self.lits.iter().any(|lit| lit.is_empty())
+    }
+
+    /// Returns true if this set is empty or if all of its members is empty.
+    pub fn is_empty(&self) -> bool {
+        self.lits.is_empty() || self.lits.iter().all(|lit| lit.is_empty())
+    }
+
+    /// Returns a new empty set of literals using this set's limits.
+    pub fn to_empty(&self) -> Literals {
+        let mut lits = Literals::empty();
+        lits.set_limit_size(self.limit_size)
+            .set_limit_class(self.limit_class);
+        lits
+    }
+
+    /// Returns the longest common prefix of all members in this set.
+    pub fn longest_common_prefix(&self) -> &[u8] {
+        if self.is_empty() {
+            return &[];
+        }
+        let lit0 = &*self.lits[0];
+        let mut len = lit0.len();
+        for lit in &self.lits[1..] {
+            len = cmp::min(
+                len,
+                lit.iter()
+                   .zip(lit0)
+                   .take_while(|&(a, b)| a == b)
+                   .count());
+        }
+        &self.lits[0][..len]
+    }
+
+    /// Returns the longest common suffix of all members in this set.
+    pub fn longest_common_suffix(&self) -> &[u8] {
+        if self.is_empty() {
+            return &[];
+        }
+        let lit0 = &*self.lits[0];
+        let mut len = lit0.len();
+        for lit in &self.lits[1..] {
+            len = cmp::min(
+                len,
+                lit.iter()
+                   .rev()
+                   .zip(lit0.iter().rev())
+                   .take_while(|&(a, b)| a == b)
+                   .count());
+        }
+        &self.lits[0][self.lits[0].len() - len..]
+    }
+
+    /// Returns a new set of literals with the given number of bytes trimmed
+    /// from the suffix of each literal.
+    ///
+    /// If any literal would be cut out completely by trimming, then None is
+    /// returned.
+    ///
+    /// Any duplicates that are created as a result of this transformation are
+    /// removed.
+    pub fn trim_suffix(&self, num_bytes: usize) -> Option<Literals> {
+        if self.min_len().map(|len| len <= num_bytes).unwrap_or(true) {
+            return None;
+        }
+        let mut new = self.to_empty();
+        for mut lit in self.lits.iter().cloned() {
+            let new_len = lit.len() - num_bytes;
+            lit.truncate(new_len);
+            lit.cut();
+            new.lits.push(lit);
+        }
+        new.lits.sort();
+        new.lits.dedup();
+        Some(new)
+    }
+
+    /// Returns a new set of prefixes of this set of literals that are
+    /// guaranteed to be unambiguous.
+    ///
+    /// Any substring match with a member of the set is returned is guaranteed
+    /// to never overlap with a substring match of another member of the set
+    /// at the same starting position.
+    ///
+    /// Given any two members of the returned set, neither is a substring of
+    /// the other.
+    pub fn unambiguous_prefixes(&self) -> Literals {
+        if self.lits.is_empty() {
+            return self.to_empty();
+        }
+        let mut old: Vec<Literal> = self.lits.iter().cloned().collect();
+        let mut new = self.to_empty();
+    'OUTER:
+        while let Some(mut candidate) = old.pop() {
+            if candidate.is_empty() {
+                continue;
+            }
+            if new.lits.is_empty() {
+                new.lits.push(candidate);
+                continue;
+            }
+            for lit2 in &mut new.lits {
+                if lit2.is_empty() {
+                    continue;
+                }
+                if &candidate == lit2 {
+                    // If the literal is already in the set, then we can
+                    // just drop it. But make sure that cut literals are
+                    // infectious!
+                    candidate.cut = candidate.cut || lit2.cut;
+                    lit2.cut = candidate.cut;
+                    continue 'OUTER;
+                }
+                if candidate.len() < lit2.len() {
+                    if let Some(i) = position(&candidate, &lit2) {
+                        candidate.cut();
+                        let mut lit3 = lit2.clone();
+                        lit3.truncate(i);
+                        lit3.cut();
+                        old.push(lit3);
+                        lit2.clear();
+                    }
+                } else {
+                    if let Some(i) = position(&lit2, &candidate) {
+                        lit2.cut();
+                        let mut new_candidate = candidate.clone();
+                        new_candidate.truncate(i);
+                        new_candidate.cut();
+                        old.push(new_candidate);
+                        candidate.clear();
+                    }
+                }
+                // Oops, the candidate is already represented in the set.
+                if candidate.is_empty() {
+                    continue 'OUTER;
+                }
+            }
+            new.lits.push(candidate);
+        }
+        new.lits.retain(|lit| !lit.is_empty());
+        new.lits.sort();
+        new.lits.dedup();
+        new
+    }
+
+    /// Returns a new set of suffixes of this set of literals that are
+    /// guaranteed to be unambiguous.
+    ///
+    /// Any substring match with a member of the set is returned is guaranteed
+    /// to never overlap with a substring match of another member of the set
+    /// at the same ending position.
+    ///
+    /// Given any two members of the returned set, neither is a substring of
+    /// the other.
+    pub fn unambiguous_suffixes(&self) -> Literals {
+        // This is a touch wasteful...
+        let mut lits = self.clone();
+        lits.reverse();
+        let mut unamb = lits.unambiguous_prefixes();
+        unamb.reverse();
+        unamb
+    }
+
+    /// Unions the prefixes from the given expression to this set.
+    ///
+    /// If prefixes could not be added (for example, this set would exceed its
+    /// size limits or the set of prefixes from `expr` includes the empty
+    /// string), then false is returned.
+    ///
+    /// Note that prefix literals extracted from `expr` are said to be complete
+    /// if and only if the literal extends from the beginning of `expr` to the
+    /// end of `expr`.
+    pub fn union_prefixes(&mut self, expr: &Hir) -> bool {
+        let mut lits = self.to_empty();
+        prefixes(expr, &mut lits);
+        !lits.is_empty() && !lits.contains_empty() && self.union(lits)
+    }
+
+    /// Unions the suffixes from the given expression to this set.
+    ///
+    /// If suffixes could not be added (for example, this set would exceed its
+    /// size limits or the set of suffixes from `expr` includes the empty
+    /// string), then false is returned.
+    ///
+    /// Note that prefix literals extracted from `expr` are said to be complete
+    /// if and only if the literal extends from the end of `expr` to the
+    /// beginning of `expr`.
+    pub fn union_suffixes(&mut self, expr: &Hir) -> bool {
+        let mut lits = self.to_empty();
+        suffixes(expr, &mut lits);
+        lits.reverse();
+        !lits.is_empty() && !lits.contains_empty() && self.union(lits)
+    }
+
+    /// Unions this set with another set.
+    ///
+    /// If the union would cause the set to exceed its limits, then the union
+    /// is skipped and it returns false. Otherwise, if the union succeeds, it
+    /// returns true.
+    pub fn union(&mut self, lits: Literals) -> bool {
+        if self.num_bytes() + lits.num_bytes() > self.limit_size {
+            return false;
+        }
+        if lits.is_empty() {
+            self.lits.push(Literal::empty());
+        } else {
+            self.lits.extend(lits.lits);
+        }
+        true
+    }
+
+    /// Extends this set with another set.
+    ///
+    /// The set of literals is extended via a cross product.
+    ///
+    /// If a cross product would cause this set to exceed its limits, then the
+    /// cross product is skipped and it returns false. Otherwise, if the cross
+    /// product succeeds, it returns true.
+    pub fn cross_product(&mut self, lits: &Literals) -> bool {
+        if lits.is_empty() {
+            return true;
+        }
+        // Check that we make sure we stay in our limits.
+        let mut size_after;
+        if self.is_empty() || !self.any_complete() {
+            size_after = self.num_bytes();
+            for lits_lit in lits.literals() {
+                size_after += lits_lit.len();
+            }
+        } else {
+            size_after = self.lits.iter().fold(0, |accum, lit| {
+                accum + if lit.is_cut() { lit.len() } else { 0 }
+            });
+            for lits_lit in lits.literals() {
+                for self_lit in self.literals() {
+                    if !self_lit.is_cut() {
+                        size_after += self_lit.len() + lits_lit.len();
+                    }
+                }
+            }
+        }
+        if size_after > self.limit_size {
+            return false;
+        }
+
+        let mut base = self.remove_complete();
+        if base.is_empty() {
+            base = vec![Literal::empty()];
+        }
+        for lits_lit in lits.literals() {
+            for mut self_lit in base.clone() {
+                self_lit.extend(&**lits_lit);
+                self_lit.cut = lits_lit.cut;
+                self.lits.push(self_lit);
+            }
+        }
+        true
+    }
+
+    /// Extends each literal in this set with the bytes given.
+    ///
+    /// If the set is empty, then the given literal is added to the set.
+    ///
+    /// If adding any number of bytes to all members of this set causes a limit
+    /// to be exceeded, then no bytes are added and false is returned. If a
+    /// prefix of `bytes` can be fit into this set, then it is used and all
+    /// resulting literals are cut.
+    pub fn cross_add(&mut self, bytes: &[u8]) -> bool {
+        // N.B. This could be implemented by simply calling cross_product with
+        // a literal set containing just `bytes`, but we can be smarter about
+        // taking shorter prefixes of `bytes` if they'll fit.
+        if bytes.is_empty() {
+            return true;
+        }
+        if self.lits.is_empty() {
+            let i = cmp::min(self.limit_size, bytes.len());
+            self.lits.push(Literal::new(bytes[..i].to_owned()));
+            self.lits[0].cut = i < bytes.len();
+            return !self.lits[0].is_cut();
+        }
+        let size = self.num_bytes();
+        if size + self.lits.len() >= self.limit_size {
+            return false;
+        }
+        let mut i = 1;
+        while size + (i * self.lits.len()) <= self.limit_size
+            && i < bytes.len() {
+            i += 1;
+        }
+        for lit in &mut self.lits {
+            if !lit.is_cut() {
+                lit.extend(&bytes[..i]);
+                if i < bytes.len() {
+                    lit.cut();
+                }
+            }
+        }
+        true
+    }
+
+    /// Adds the given literal to this set.
+    ///
+    /// Returns false if adding this literal would cause the class to be too
+    /// big.
+    pub fn add(&mut self, lit: Literal) -> bool {
+        if self.num_bytes() + lit.len() > self.limit_size {
+            return false;
+        }
+        self.lits.push(lit);
+        true
+    }
+
+    /// Extends each literal in this set with the character class given.
+    ///
+    /// Returns false if the character class was too big to add.
+    pub fn add_char_class(&mut self, cls: &hir::ClassUnicode) -> bool {
+        self._add_char_class(cls, false)
+    }
+
+    /// Extends each literal in this set with the character class given,
+    /// writing the bytes of each character in reverse.
+    ///
+    /// Returns false if the character class was too big to add.
+    fn add_char_class_reverse(&mut self, cls: &hir::ClassUnicode) -> bool {
+        self._add_char_class(cls, true)
+    }
+
+    fn _add_char_class(
+        &mut self,
+        cls: &hir::ClassUnicode,
+        reverse: bool,
+    ) -> bool {
+        use std::char;
+
+        if self.class_exceeds_limits(cls_char_count(cls)) {
+            return false;
+        }
+        let mut base = self.remove_complete();
+        if base.is_empty() {
+            base = vec![Literal::empty()];
+        }
+        for r in cls.iter() {
+            let (s, e) = (r.start as u32, r.end as u32 + 1);
+            for c in (s..e).filter_map(char::from_u32) {
+                for mut lit in base.clone() {
+                    let mut bytes = c.to_string().into_bytes();
+                    if reverse {
+                        bytes.reverse();
+                    }
+                    lit.extend(&bytes);
+                    self.lits.push(lit);
+                }
+            }
+        }
+        true
+    }
+
+    /// Extends each literal in this set with the byte class given.
+    ///
+    /// Returns false if the byte class was too big to add.
+    pub fn add_byte_class(&mut self, cls: &hir::ClassBytes) -> bool {
+        if self.class_exceeds_limits(cls_byte_count(cls)) {
+            return false;
+        }
+        let mut base = self.remove_complete();
+        if base.is_empty() {
+            base = vec![Literal::empty()];
+        }
+        for r in cls.iter() {
+            let (s, e) = (r.start as u32, r.end as u32 + 1);
+            for b in (s..e).map(|b| b as u8) {
+                for mut lit in base.clone() {
+                    lit.push(b);
+                    self.lits.push(lit);
+                }
+            }
+        }
+        true
+    }
+
+    /// Cuts every member of this set. When a member is cut, it can never
+    /// be extended.
+    pub fn cut(&mut self) {
+        for lit in &mut self.lits {
+            lit.cut();
+        }
+    }
+
+    /// Reverses all members in place.
+    pub fn reverse(&mut self) {
+        for lit in &mut self.lits {
+            lit.reverse();
+        }
+    }
+
+    /// Clears this set of all members.
+    pub fn clear(&mut self) {
+        self.lits.clear();
+    }
+
+    /// Pops all complete literals out of this set.
+    fn remove_complete(&mut self) -> Vec<Literal> {
+        let mut base = vec![];
+        for lit in mem::replace(&mut self.lits, vec![]) {
+            if lit.is_cut() {
+                self.lits.push(lit);
+            } else {
+                base.push(lit);
+            }
+        }
+        base
+    }
+
+    /// Returns the total number of bytes in this set.
+    fn num_bytes(&self) -> usize {
+        self.lits.iter().fold(0, |accum, lit| accum + lit.len())
+    }
+
+    /// Returns true if a character class with the given size would cause this
+    /// set to exceed its limits.
+    ///
+    /// The size given should correspond to the number of items in the class.
+    fn class_exceeds_limits(&self, size: usize) -> bool {
+        if size > self.limit_class {
+            return true;
+        }
+        // This is an approximation since codepoints in a char class can encode
+        // to 1-4 bytes.
+        let new_byte_count =
+            if self.lits.is_empty() {
+                size
+            } else {
+                self.lits
+                    .iter()
+                    .fold(0, |accum, lit| {
+                        accum + if lit.is_cut() {
+                            // If the literal is cut, then we'll never add
+                            // anything to it, so don't count it.
+                            0
+                        } else {
+                            (lit.len() + 1) * size
+                        }
+                    })
+            };
+        new_byte_count > self.limit_size
+    }
+}
+
+fn prefixes(expr: &Hir, lits: &mut Literals) {
+    match *expr.kind() {
+        HirKind::Literal(hir::Literal::Unicode(c)) => {
+            let mut buf = [0; 4];
+            lits.cross_add(c.encode_utf8(&mut buf).as_bytes());
+        }
+        HirKind::Literal(hir::Literal::Byte(b)) => {
+            lits.cross_add(&[b]);
+        }
+        HirKind::Class(hir::Class::Unicode(ref cls)) => {
+            if !lits.add_char_class(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Class(hir::Class::Bytes(ref cls)) => {
+            if !lits.add_byte_class(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Group(hir::Group { ref hir, .. }) => {
+            prefixes(&**hir, lits);
+        }
+        HirKind::Repetition(ref x) => {
+            match x.kind {
+                hir::RepetitionKind::ZeroOrOne => {
+                    repeat_zero_or_one_literals(&x.hir, lits, prefixes);
+                }
+                hir::RepetitionKind::ZeroOrMore => {
+                    repeat_zero_or_more_literals(&x.hir, lits, prefixes);
+                }
+                hir::RepetitionKind::OneOrMore => {
+                    repeat_one_or_more_literals(&x.hir, lits, prefixes);
+                }
+                hir::RepetitionKind::Range(ref rng) => {
+                    let (min, max) = match *rng {
+                        hir::RepetitionRange::Exactly(m) => {
+                            (m, Some(m))
+                        }
+                        hir::RepetitionRange::AtLeast(m) => {
+                            (m, None)
+                        }
+                        hir::RepetitionRange::Bounded(m, n) => {
+                            (m, Some(n))
+                        }
+                    };
+                    repeat_range_literals(
+                        &x.hir, min, max, x.greedy, lits, prefixes)
+                }
+            }
+        }
+        HirKind::Concat(ref es) if es.is_empty() => {}
+        HirKind::Concat(ref es) if es.len() == 1 => prefixes(&es[0], lits),
+        HirKind::Concat(ref es) => {
+            for e in es {
+                if let HirKind::Anchor(hir::Anchor::StartText) = *e.kind() {
+                    if !lits.is_empty() {
+                        lits.cut();
+                        break;
+                    }
+                    lits.add(Literal::empty());
+                    continue;
+                }
+                let mut lits2 = lits.to_empty();
+                prefixes(e, &mut lits2);
+                if !lits.cross_product(&lits2) || !lits2.any_complete() {
+                    // If this expression couldn't yield any literal that
+                    // could be extended, then we need to quit. Since we're
+                    // short-circuiting, we also need to freeze every member.
+                    lits.cut();
+                    break;
+                }
+            }
+        }
+        HirKind::Alternation(ref es) => {
+            alternate_literals(es, lits, prefixes);
+        }
+        _ => lits.cut(),
+    }
+}
+
+fn suffixes(expr: &Hir, lits: &mut Literals) {
+    match *expr.kind() {
+        HirKind::Literal(hir::Literal::Unicode(c)) => {
+            let mut buf = [0u8; 4];
+            let i = c.encode_utf8(&mut buf).len();
+            let mut buf = &mut buf[..i];
+            buf.reverse();
+            lits.cross_add(buf);
+        }
+        HirKind::Literal(hir::Literal::Byte(b)) => {
+            lits.cross_add(&[b]);
+        }
+        HirKind::Class(hir::Class::Unicode(ref cls)) => {
+            if !lits.add_char_class_reverse(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Class(hir::Class::Bytes(ref cls)) => {
+            if !lits.add_byte_class(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Group(hir::Group { ref hir, .. }) => {
+            suffixes(&**hir, lits);
+        }
+        HirKind::Repetition(ref x) => {
+            match x.kind {
+                hir::RepetitionKind::ZeroOrOne => {
+                    repeat_zero_or_one_literals(&x.hir, lits, suffixes);
+                }
+                hir::RepetitionKind::ZeroOrMore => {
+                    repeat_zero_or_more_literals(&x.hir, lits, suffixes);
+                }
+                hir::RepetitionKind::OneOrMore => {
+                    repeat_one_or_more_literals(&x.hir, lits, suffixes);
+                }
+                hir::RepetitionKind::Range(ref rng) => {
+                    let (min, max) = match *rng {
+                        hir::RepetitionRange::Exactly(m) => {
+                            (m, Some(m))
+                        }
+                        hir::RepetitionRange::AtLeast(m) => {
+                            (m, None)
+                        }
+                        hir::RepetitionRange::Bounded(m, n) => {
+                            (m, Some(n))
+                        }
+                    };
+                    repeat_range_literals(
+                        &x.hir, min, max, x.greedy, lits, suffixes)
+                }
+            }
+        }
+        HirKind::Concat(ref es) if es.is_empty() => {}
+        HirKind::Concat(ref es) if es.len() == 1 => suffixes(&es[0], lits),
+        HirKind::Concat(ref es) => {
+            for e in es.iter().rev() {
+                if let HirKind::Anchor(hir::Anchor::EndText) = *e.kind() {
+                    if !lits.is_empty() {
+                        lits.cut();
+                        break;
+                    }
+                    lits.add(Literal::empty());
+                    continue;
+                }
+                let mut lits2 = lits.to_empty();
+                suffixes(e, &mut lits2);
+                if !lits.cross_product(&lits2) || !lits2.any_complete() {
+                    // If this expression couldn't yield any literal that
+                    // could be extended, then we need to quit. Since we're
+                    // short-circuiting, we also need to freeze every member.
+                    lits.cut();
+                    break;
+                }
+            }
+        }
+        HirKind::Alternation(ref es) => {
+            alternate_literals(es, lits, suffixes);
+        }
+        _ => lits.cut(),
+    }
+}
+
+fn repeat_zero_or_one_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    let (mut lits2, mut lits3) = (lits.clone(), lits.to_empty());
+    lits3.set_limit_size(lits.limit_size() / 2);
+    f(e, &mut lits3);
+
+    if lits3.is_empty() || !lits2.cross_product(&lits3) {
+        lits.cut();
+        return;
+    }
+    lits2.add(Literal::empty());
+    if !lits.union(lits2) {
+        lits.cut();
+    }
+}
+
+fn repeat_zero_or_more_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    let (mut lits2, mut lits3) = (lits.clone(), lits.to_empty());
+    lits3.set_limit_size(lits.limit_size() / 2);
+    f(e, &mut lits3);
+
+    if lits3.is_empty() || !lits2.cross_product(&lits3) {
+        lits.cut();
+        return;
+    }
+    lits2.cut();
+    lits2.add(Literal::empty());
+    if !lits.union(lits2) {
+        lits.cut();
+    }
+}
+
+fn repeat_one_or_more_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    f(e, lits);
+    lits.cut();
+}
+
+fn repeat_range_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    min: u32,
+    max: Option<u32>,
+    greedy: bool,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    if min == 0 {
+        // This is a bit conservative. If `max` is set, then we could
+        // treat this as a finite set of alternations. For now, we
+        // just treat it as `e*`.
+        f(&Hir::repetition(hir::Repetition {
+            kind: hir::RepetitionKind::ZeroOrMore,
+            greedy: greedy,
+            hir: Box::new(e.clone()),
+        }), lits);
+    } else {
+        if min > 0 {
+            let n = cmp::min(lits.limit_size, min as usize);
+            let es = iter::repeat(e.clone()).take(n).collect();
+            f(&Hir::concat(es), lits);
+            if n < min as usize || lits.contains_empty() {
+                lits.cut();
+            }
+        }
+        if max.map_or(true, |max| min < max) {
+            lits.cut();
+        }
+    }
+}
+
+fn alternate_literals<F: FnMut(&Hir, &mut Literals)>(
+    es: &[Hir],
+    lits: &mut Literals,
+    mut f: F,
+) {
+    let mut lits2 = lits.to_empty();
+    for e in es {
+        let mut lits3 = lits.to_empty();
+        lits3.set_limit_size(lits.limit_size() / 5);
+        f(e, &mut lits3);
+        if lits3.is_empty() || !lits2.union(lits3) {
+            // If we couldn't find suffixes for *any* of the
+            // alternates, then the entire alternation has to be thrown
+            // away and any existing members must be frozen. Similarly,
+            // if the union couldn't complete, stop and freeze.
+            lits.cut();
+            return;
+        }
+    }
+    if !lits.cross_product(&lits2) {
+        lits.cut();
+    }
+}
+
+impl fmt::Debug for Literals {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Literals")
+         .field("lits", &self.lits)
+         .field("limit_size", &self.limit_size)
+         .field("limit_class", &self.limit_class)
+         .finish()
+    }
+}
+
+impl Literal {
+    /// Returns a new complete literal with the bytes given.
+    pub fn new(bytes: Vec<u8>) -> Literal {
+        Literal { v: bytes, cut: false }
+    }
+
+    /// Returns a new complete empty literal.
+    pub fn empty() -> Literal {
+        Literal { v: vec![], cut: false }
+    }
+
+    /// Returns true if this literal was "cut."
+    pub fn is_cut(&self) -> bool {
+        self.cut
+    }
+
+    /// Cuts this literal.
+    pub fn cut(&mut self) {
+        self.cut = true;
+    }
+}
+
+impl PartialEq for Literal {
+    fn eq(&self, other: &Literal) -> bool {
+        self.v == other.v
+    }
+}
+
+impl PartialOrd for Literal {
+    fn partial_cmp(&self, other: &Literal) -> Option<cmp::Ordering> {
+        self.v.partial_cmp(&other.v)
+    }
+}
+
+impl fmt::Debug for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.is_cut() {
+            write!(f, "Cut({})", escape_unicode(&self.v))
+        } else {
+            write!(f, "Complete({})", escape_unicode(&self.v))
+        }
+    }
+}
+
+impl AsRef<[u8]> for Literal {
+    fn as_ref(&self) -> &[u8] { &self.v }
+}
+
+impl ops::Deref for Literal {
+    type Target = Vec<u8>;
+    fn deref(&self) -> &Vec<u8> { &self.v }
+}
+
+impl ops::DerefMut for Literal {
+    fn deref_mut(&mut self) -> &mut Vec<u8> { &mut self.v }
+}
+
+fn position(needle: &[u8], mut haystack: &[u8]) -> Option<usize> {
+    let mut i = 0;
+    while haystack.len() >= needle.len() {
+        if needle == &haystack[..needle.len()] {
+            return Some(i);
+        }
+        i += 1;
+        haystack = &haystack[1..];
+    }
+    None
+}
+
+fn escape_unicode(bytes: &[u8]) -> String {
+    let show = match ::std::str::from_utf8(bytes) {
+        Ok(v) => v.to_string(),
+        Err(_) => escape_bytes(bytes),
+    };
+    let mut space_escaped = String::new();
+    for c in show.chars() {
+        if c.is_whitespace() {
+            let escaped = if c as u32 <= 0x7F {
+                escape_byte(c as u8)
+            } else {
+                if c as u32 <= 0xFFFF {
+                    format!(r"\u{{{:04x}}}", c as u32)
+                } else {
+                    format!(r"\U{{{:08x}}}", c as u32)
+                }
+            };
+            space_escaped.push_str(&escaped);
+        } else {
+            space_escaped.push(c);
+        }
+    }
+    space_escaped
+}
+
+fn escape_bytes(bytes: &[u8]) -> String {
+    let mut s = String::new();
+    for &b in bytes {
+        s.push_str(&escape_byte(b));
+    }
+    s
+}
+
+fn escape_byte(byte: u8) -> String {
+    use std::ascii::escape_default;
+
+    let escaped: Vec<u8> = escape_default(byte).collect();
+    String::from_utf8_lossy(&escaped).into_owned()
+}
+
+fn cls_char_count(cls: &hir::ClassUnicode) -> usize {
+    cls.iter()
+        .map(|&r| 1 + (r.end as u32) - (r.start as u32))
+        .sum::<u32>() as usize
+}
+
+fn cls_byte_count(cls: &hir::ClassBytes) -> usize {
+    cls.iter()
+        .map(|&r| 1 + (r.end as u32) - (r.start as u32))
+        .sum::<u32>() as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use std::fmt;
+
+    use ParserBuilder;
+    use hir::Hir;
+    use super::{Literals, Literal, escape_bytes};
+
+    // To make test failures easier to read.
+    #[derive(Debug, Eq, PartialEq)]
+    struct Bytes(Vec<ULiteral>);
+    #[derive(Debug, Eq, PartialEq)]
+    struct Unicode(Vec<ULiteral>);
+
+    fn escape_lits(blits: &[Literal]) -> Vec<ULiteral> {
+        let mut ulits = vec![];
+        for blit in blits {
+            ulits.push(ULiteral {
+                v: escape_bytes(&blit),
+                cut: blit.is_cut(),
+            });
+        }
+        ulits
+    }
+
+    fn create_lits<I: IntoIterator<Item=Literal>>(it: I) -> Literals {
+        Literals {
+            lits: it.into_iter().collect(),
+            limit_size: 0,
+            limit_class: 0,
+        }
+    }
+
+    // Needs to be pub for 1.3?
+    #[derive(Clone, Eq, PartialEq)]
+    pub struct ULiteral {
+        v: String,
+        cut: bool,
+    }
+
+    impl ULiteral {
+        fn is_cut(&self) -> bool { self.cut }
+    }
+
+    impl fmt::Debug for ULiteral {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            if self.is_cut() {
+                write!(f, "Cut({})", self.v)
+            } else {
+                write!(f, "Complete({})", self.v)
+            }
+        }
+    }
+
+    impl PartialEq<Literal> for ULiteral {
+        fn eq(&self, other: &Literal) -> bool {
+            self.v.as_bytes() == &*other.v && self.is_cut() == other.is_cut()
+        }
+    }
+
+    impl PartialEq<ULiteral> for Literal {
+        fn eq(&self, other: &ULiteral) -> bool {
+            &*self.v == other.v.as_bytes() && self.is_cut() == other.is_cut()
+        }
+    }
+
+    #[allow(non_snake_case)]
+    fn C(s: &'static str) -> ULiteral {
+        ULiteral { v: s.to_owned(), cut: true }
+    }
+    #[allow(non_snake_case)]
+    fn M(s: &'static str) -> ULiteral {
+        ULiteral { v: s.to_owned(), cut: false }
+    }
+
+    fn prefixes(lits: &mut Literals, expr: &Hir) {
+        lits.union_prefixes(expr);
+    }
+
+    fn suffixes(lits: &mut Literals, expr: &Hir) {
+        lits.union_suffixes(expr);
+    }
+
+    macro_rules! assert_lit_eq {
+        ($which:ident, $got_lits:expr, $($expected_lit:expr),*) => {{
+            let expected: Vec<ULiteral> = vec![$($expected_lit),*];
+            let lits = $got_lits;
+            assert_eq!(
+                $which(expected.clone()),
+                $which(escape_lits(lits.literals())));
+            assert_eq!(
+                !expected.is_empty() && expected.iter().all(|l| !l.is_cut()),
+                lits.all_complete());
+            assert_eq!(
+                expected.iter().any(|l| !l.is_cut()),
+                lits.any_complete());
+        }};
+    }
+
+    macro_rules! test_lit {
+        ($name:ident, $which:ident, $re:expr) => {
+            test_lit!($name, $which, $re,);
+        };
+        ($name:ident, $which:ident, $re:expr, $($lit:expr),*) => {
+            #[test]
+            fn $name() {
+                let expr = ParserBuilder::new()
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let lits = Literals::$which(&expr);
+                assert_lit_eq!(Unicode, lits, $($lit),*);
+
+                let expr = ParserBuilder::new()
+                    .allow_invalid_utf8(true)
+                    .unicode(false)
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let lits = Literals::$which(&expr);
+                assert_lit_eq!(Bytes, lits, $($lit),*);
+            }
+        };
+    }
+
+    // ************************************************************************
+    // Tests for prefix literal extraction.
+    // ************************************************************************
+
+    // Elementary tests.
+    test_lit!(pfx_one_lit1, prefixes, "a", M("a"));
+    test_lit!(pfx_one_lit2, prefixes, "abc", M("abc"));
+    test_lit!(pfx_one_lit3, prefixes, "(?u)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_one_lit4, prefixes, "(?ui)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_class1, prefixes, "[1-4]",
+              M("1"), M("2"), M("3"), M("4"));
+    test_lit!(pfx_class2, prefixes, "(?u)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_class3, prefixes, "(?ui)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x85\\xb0"),
+              M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_one_lit_casei1, prefixes, "(?i)a",
+              M("A"), M("a"));
+    test_lit!(pfx_one_lit_casei2, prefixes, "(?i)abc",
+              M("ABC"), M("aBC"), M("AbC"), M("abC"),
+              M("ABc"), M("aBc"), M("Abc"), M("abc"));
+    test_lit!(pfx_group1, prefixes, "(a)", M("a"));
+    test_lit!(pfx_rep_zero_or_one1, prefixes, "a?");
+    test_lit!(pfx_rep_zero_or_one2, prefixes, "(?:abc)?");
+    test_lit!(pfx_rep_zero_or_more1, prefixes, "a*");
+    test_lit!(pfx_rep_zero_or_more2, prefixes, "(?:abc)*");
+    test_lit!(pfx_rep_one_or_more1, prefixes, "a+", C("a"));
+    test_lit!(pfx_rep_one_or_more2, prefixes, "(?:abc)+", C("abc"));
+    test_lit!(pfx_rep_nested_one_or_more, prefixes, "(?:a+)+", C("a"));
+    test_lit!(pfx_rep_range1, prefixes, "a{0}");
+    test_lit!(pfx_rep_range2, prefixes, "a{0,}");
+    test_lit!(pfx_rep_range3, prefixes, "a{0,1}");
+    test_lit!(pfx_rep_range4, prefixes, "a{1}", M("a"));
+    test_lit!(pfx_rep_range5, prefixes, "a{2}", M("aa"));
+    test_lit!(pfx_rep_range6, prefixes, "a{1,2}", C("a"));
+    test_lit!(pfx_rep_range7, prefixes, "a{2,3}", C("aa"));
+
+    // Test regexes with concatenations.
+    test_lit!(pfx_cat1, prefixes, "(?:a)(?:b)", M("ab"));
+    test_lit!(pfx_cat2, prefixes, "[ab]z", M("az"), M("bz"));
+    test_lit!(pfx_cat3, prefixes, "(?i)[ab]z",
+              M("AZ"), M("BZ"), M("aZ"), M("bZ"),
+              M("Az"), M("Bz"), M("az"), M("bz"));
+    test_lit!(pfx_cat4, prefixes, "[ab][yz]",
+              M("ay"), M("by"), M("az"), M("bz"));
+    test_lit!(pfx_cat5, prefixes, "a*b", C("a"), M("b"));
+    test_lit!(pfx_cat6, prefixes, "a*b*c", C("a"), C("b"), M("c"));
+    test_lit!(pfx_cat7, prefixes, "a*b*c+", C("a"), C("b"), C("c"));
+    test_lit!(pfx_cat8, prefixes, "a*b+c", C("a"), C("b"));
+    test_lit!(pfx_cat9, prefixes, "a*b+c*", C("a"), C("b"));
+    test_lit!(pfx_cat10, prefixes, "ab*", C("ab"), M("a"));
+    test_lit!(pfx_cat11, prefixes, "ab*c", C("ab"), M("ac"));
+    test_lit!(pfx_cat12, prefixes, "ab+", C("ab"));
+    test_lit!(pfx_cat13, prefixes, "ab+c", C("ab"));
+    test_lit!(pfx_cat14, prefixes, "a^", C("a"));
+    test_lit!(pfx_cat15, prefixes, "$a");
+    test_lit!(pfx_cat16, prefixes, r"ab*c", C("ab"), M("ac"));
+    test_lit!(pfx_cat17, prefixes, r"ab+c", C("ab"));
+    test_lit!(pfx_cat18, prefixes, r"z*azb", C("z"), M("azb"));
+    test_lit!(pfx_cat19, prefixes, "a.z", C("a"));
+
+    // Test regexes with alternations.
+    test_lit!(pfx_alt1, prefixes, "a|b", M("a"), M("b"));
+    test_lit!(pfx_alt2, prefixes, "[1-3]|b", M("1"), M("2"), M("3"), M("b"));
+    test_lit!(pfx_alt3, prefixes, "y(?:a|b)z", M("yaz"), M("ybz"));
+    test_lit!(pfx_alt4, prefixes, "a|b*");
+    test_lit!(pfx_alt5, prefixes, "a|b+", M("a"), C("b"));
+    test_lit!(pfx_alt6, prefixes, "a|(?:b|c*)");
+    test_lit!(pfx_alt7, prefixes, "(a|b)*c|(a|ab)*c",
+              C("a"), C("b"), M("c"), C("a"), C("ab"), M("c"));
+    test_lit!(pfx_alt8, prefixes, "a*b|c", C("a"), M("b"), M("c"));
+
+    // Test regexes with empty assertions.
+    test_lit!(pfx_empty1, prefixes, "^a", M("a"));
+    test_lit!(pfx_empty2, prefixes, "a${2}", C("a"));
+    test_lit!(pfx_empty3, prefixes, "^abc", M("abc"));
+    test_lit!(pfx_empty4, prefixes, "(?:^abc)|(?:^z)", M("abc"), M("z"));
+
+    // Make sure some curious regexes have no prefixes.
+    test_lit!(pfx_nothing1, prefixes, ".");
+    test_lit!(pfx_nothing2, prefixes, "(?s).");
+    test_lit!(pfx_nothing3, prefixes, "^");
+    test_lit!(pfx_nothing4, prefixes, "$");
+    test_lit!(pfx_nothing6, prefixes, "(?m)$");
+    test_lit!(pfx_nothing7, prefixes, r"\b");
+    test_lit!(pfx_nothing8, prefixes, r"\B");
+
+    // Test a few regexes that defeat any prefix literal detection.
+    test_lit!(pfx_defeated1, prefixes, ".a");
+    test_lit!(pfx_defeated2, prefixes, "(?s).a");
+    test_lit!(pfx_defeated3, prefixes, "a*b*c*");
+    test_lit!(pfx_defeated4, prefixes, "a|.");
+    test_lit!(pfx_defeated5, prefixes, ".|a");
+    test_lit!(pfx_defeated6, prefixes, "a|^");
+    test_lit!(pfx_defeated7, prefixes, ".(?:a(?:b)(?:c))");
+    test_lit!(pfx_defeated8, prefixes, "$a");
+    test_lit!(pfx_defeated9, prefixes, "(?m)$a");
+    test_lit!(pfx_defeated10, prefixes, r"\ba");
+    test_lit!(pfx_defeated11, prefixes, r"\Ba");
+    test_lit!(pfx_defeated12, prefixes, "^*a");
+    test_lit!(pfx_defeated13, prefixes, "^+a");
+
+    test_lit!(
+        pfx_crazy1,
+        prefixes,
+        r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+        C("Mo\\'am"), C("Mu\\'am"), C("Moam"), C("Muam"));
+
+    // ************************************************************************
+    // Tests for quiting prefix literal search.
+    // ************************************************************************
+
+    macro_rules! test_exhausted {
+        ($name:ident, $which:ident, $re:expr) => {
+            test_exhausted!($name, $which, $re,);
+        };
+        ($name:ident, $which:ident, $re:expr, $($lit:expr),*) => {
+            #[test]
+            fn $name() {
+                let expr = ParserBuilder::new()
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let mut lits = Literals::empty();
+                lits.set_limit_size(20).set_limit_class(10);
+                $which(&mut lits, &expr);
+                assert_lit_eq!(Unicode, lits, $($lit),*);
+
+                let expr = ParserBuilder::new()
+                    .allow_invalid_utf8(true)
+                    .unicode(false)
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let mut lits = Literals::empty();
+                lits.set_limit_size(20).set_limit_class(10);
+                $which(&mut lits, &expr);
+                assert_lit_eq!(Bytes, lits, $($lit),*);
+            }
+        };
+    }
+
+    // These test use a much lower limit than the default so that we can
+    // write test cases of reasonable size.
+    test_exhausted!(pfx_exhausted1, prefixes, "[a-z]");
+    test_exhausted!(pfx_exhausted2, prefixes, "[a-z]*A");
+    test_exhausted!(pfx_exhausted3, prefixes, "A[a-z]Z", C("A"));
+    test_exhausted!(pfx_exhausted4, prefixes, "(?i)foobar",
+                    C("FO"), C("fO"), C("Fo"), C("fo"));
+    test_exhausted!(pfx_exhausted5, prefixes, "(?:ab){100}",
+                    C("abababababababababab"));
+    test_exhausted!(pfx_exhausted6, prefixes, "(?:(?:ab){100})*cd",
+                    C("ababababab"), M("cd"));
+    test_exhausted!(pfx_exhausted7, prefixes, "z(?:(?:ab){100})*cd",
+                    C("zababababab"), M("zcd"));
+    test_exhausted!(pfx_exhausted8, prefixes, "aaaaaaaaaaaaaaaaaaaaz",
+                    C("aaaaaaaaaaaaaaaaaaaa"));
+
+    // ************************************************************************
+    // Tests for suffix literal extraction.
+    // ************************************************************************
+
+    // Elementary tests.
+    test_lit!(sfx_one_lit1, suffixes, "a", M("a"));
+    test_lit!(sfx_one_lit2, suffixes, "abc", M("abc"));
+    test_lit!(sfx_one_lit3, suffixes, "(?u)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_one_lit4, suffixes, "(?ui)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_class1, suffixes, "[1-4]",
+              M("1"), M("2"), M("3"), M("4"));
+    test_lit!(sfx_class2, suffixes, "(?u)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_class3, suffixes, "(?ui)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x85\\xb0"),
+              M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_one_lit_casei1, suffixes, "(?i)a",
+              M("A"), M("a"));
+    test_lit!(sfx_one_lit_casei2, suffixes, "(?i)abc",
+              M("ABC"), M("ABc"), M("AbC"), M("Abc"),
+              M("aBC"), M("aBc"), M("abC"), M("abc"));
+    test_lit!(sfx_group1, suffixes, "(a)", M("a"));
+    test_lit!(sfx_rep_zero_or_one1, suffixes, "a?");
+    test_lit!(sfx_rep_zero_or_one2, suffixes, "(?:abc)?");
+    test_lit!(sfx_rep_zero_or_more1, suffixes, "a*");
+    test_lit!(sfx_rep_zero_or_more2, suffixes, "(?:abc)*");
+    test_lit!(sfx_rep_one_or_more1, suffixes, "a+", C("a"));
+    test_lit!(sfx_rep_one_or_more2, suffixes, "(?:abc)+", C("abc"));
+    test_lit!(sfx_rep_nested_one_or_more, suffixes, "(?:a+)+", C("a"));
+    test_lit!(sfx_rep_range1, suffixes, "a{0}");
+    test_lit!(sfx_rep_range2, suffixes, "a{0,}");
+    test_lit!(sfx_rep_range3, suffixes, "a{0,1}");
+    test_lit!(sfx_rep_range4, suffixes, "a{1}", M("a"));
+    test_lit!(sfx_rep_range5, suffixes, "a{2}", M("aa"));
+    test_lit!(sfx_rep_range6, suffixes, "a{1,2}", C("a"));
+    test_lit!(sfx_rep_range7, suffixes, "a{2,3}", C("aa"));
+
+    // Test regexes with concatenations.
+    test_lit!(sfx_cat1, suffixes, "(?:a)(?:b)", M("ab"));
+    test_lit!(sfx_cat2, suffixes, "[ab]z", M("az"), M("bz"));
+    test_lit!(sfx_cat3, suffixes, "(?i)[ab]z",
+              M("AZ"), M("Az"), M("BZ"), M("Bz"),
+              M("aZ"), M("az"), M("bZ"), M("bz"));
+    test_lit!(sfx_cat4, suffixes, "[ab][yz]",
+              M("ay"), M("az"), M("by"), M("bz"));
+    test_lit!(sfx_cat5, suffixes, "a*b", C("ab"), M("b"));
+    test_lit!(sfx_cat6, suffixes, "a*b*c", C("bc"), C("ac"), M("c"));
+    test_lit!(sfx_cat7, suffixes, "a*b*c+", C("c"));
+    test_lit!(sfx_cat8, suffixes, "a*b+c", C("bc"));
+    test_lit!(sfx_cat9, suffixes, "a*b+c*", C("c"), C("b"));
+    test_lit!(sfx_cat10, suffixes, "ab*", C("b"), M("a"));
+    test_lit!(sfx_cat11, suffixes, "ab*c", C("bc"), M("ac"));
+    test_lit!(sfx_cat12, suffixes, "ab+", C("b"));
+    test_lit!(sfx_cat13, suffixes, "ab+c", C("bc"));
+    test_lit!(sfx_cat14, suffixes, "a^");
+    test_lit!(sfx_cat15, suffixes, "$a", C("a"));
+    test_lit!(sfx_cat16, suffixes, r"ab*c", C("bc"), M("ac"));
+    test_lit!(sfx_cat17, suffixes, r"ab+c", C("bc"));
+    test_lit!(sfx_cat18, suffixes, r"z*azb", C("zazb"), M("azb"));
+    test_lit!(sfx_cat19, suffixes, "a.z", C("z"));
+
+    // Test regexes with alternations.
+    test_lit!(sfx_alt1, suffixes, "a|b", M("a"), M("b"));
+    test_lit!(sfx_alt2, suffixes, "[1-3]|b", M("1"), M("2"), M("3"), M("b"));
+    test_lit!(sfx_alt3, suffixes, "y(?:a|b)z", M("yaz"), M("ybz"));
+    test_lit!(sfx_alt4, suffixes, "a|b*");
+    test_lit!(sfx_alt5, suffixes, "a|b+", M("a"), C("b"));
+    test_lit!(sfx_alt6, suffixes, "a|(?:b|c*)");
+    test_lit!(sfx_alt7, suffixes, "(a|b)*c|(a|ab)*c",
+              C("ac"), C("bc"), M("c"), C("ac"), C("abc"), M("c"));
+    test_lit!(sfx_alt8, suffixes, "a*b|c", C("ab"), M("b"), M("c"));
+
+    // Test regexes with empty assertions.
+    test_lit!(sfx_empty1, suffixes, "a$", M("a"));
+    test_lit!(sfx_empty2, suffixes, "${2}a", C("a"));
+
+    // Make sure some curious regexes have no suffixes.
+    test_lit!(sfx_nothing1, suffixes, ".");
+    test_lit!(sfx_nothing2, suffixes, "(?s).");
+    test_lit!(sfx_nothing3, suffixes, "^");
+    test_lit!(sfx_nothing4, suffixes, "$");
+    test_lit!(sfx_nothing6, suffixes, "(?m)$");
+    test_lit!(sfx_nothing7, suffixes, r"\b");
+    test_lit!(sfx_nothing8, suffixes, r"\B");
+
+    // Test a few regexes that defeat any suffix literal detection.
+    test_lit!(sfx_defeated1, suffixes, "a.");
+    test_lit!(sfx_defeated2, suffixes, "(?s)a.");
+    test_lit!(sfx_defeated3, suffixes, "a*b*c*");
+    test_lit!(sfx_defeated4, suffixes, "a|.");
+    test_lit!(sfx_defeated5, suffixes, ".|a");
+    test_lit!(sfx_defeated6, suffixes, "a|^");
+    test_lit!(sfx_defeated7, suffixes, "(?:a(?:b)(?:c)).");
+    test_lit!(sfx_defeated8, suffixes, "a^");
+    test_lit!(sfx_defeated9, suffixes, "(?m)a$");
+    test_lit!(sfx_defeated10, suffixes, r"a\b");
+    test_lit!(sfx_defeated11, suffixes, r"a\B");
+    test_lit!(sfx_defeated12, suffixes, "a^*");
+    test_lit!(sfx_defeated13, suffixes, "a^+");
+
+    // These test use a much lower limit than the default so that we can
+    // write test cases of reasonable size.
+    test_exhausted!(sfx_exhausted1, suffixes, "[a-z]");
+    test_exhausted!(sfx_exhausted2, suffixes, "A[a-z]*");
+    test_exhausted!(sfx_exhausted3, suffixes, "A[a-z]Z", C("Z"));
+    test_exhausted!(sfx_exhausted4, suffixes, "(?i)foobar",
+                    C("AR"), C("Ar"), C("aR"), C("ar"));
+    test_exhausted!(sfx_exhausted5, suffixes, "(?:ab){100}",
+                    C("abababababababababab"));
+    test_exhausted!(sfx_exhausted6, suffixes, "cd(?:(?:ab){100})*",
+                    C("ababababab"), M("cd"));
+    test_exhausted!(sfx_exhausted7, suffixes, "cd(?:(?:ab){100})*z",
+                    C("abababababz"), M("cdz"));
+    test_exhausted!(sfx_exhausted8, suffixes, "zaaaaaaaaaaaaaaaaaaaa",
+                    C("aaaaaaaaaaaaaaaaaaaa"));
+
+    // ************************************************************************
+    // Tests for generating unambiguous literal sets.
+    // ************************************************************************
+
+    macro_rules! test_unamb {
+        ($name:ident, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|ul| {
+                        let cut = ul.is_cut();
+                        Literal { v: ul.v.into_bytes(), cut: cut }
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.unambiguous_prefixes();
+                assert_eq!($expected, escape_lits(got.literals()));
+            }
+        };
+    }
+
+    test_unamb!(unambiguous1, vec![M("z"), M("azb")], vec![C("a"), C("z")]);
+    test_unamb!(unambiguous2,
+                vec![M("zaaaaaa"), M("aa")], vec![C("aa"), C("z")]);
+    test_unamb!(unambiguous3,
+                vec![M("Sherlock"), M("Watson")],
+                vec![M("Sherlock"), M("Watson")]);
+    test_unamb!(unambiguous4, vec![M("abc"), M("bc")], vec![C("a"), C("bc")]);
+    test_unamb!(unambiguous5, vec![M("bc"), M("abc")], vec![C("a"), C("bc")]);
+    test_unamb!(unambiguous6, vec![M("a"), M("aa")], vec![C("a")]);
+    test_unamb!(unambiguous7, vec![M("aa"), M("a")], vec![C("a")]);
+    test_unamb!(unambiguous8, vec![M("ab"), M("a")], vec![C("a")]);
+    test_unamb!(unambiguous9,
+                vec![M("ac"), M("bc"), M("c"), M("ac"), M("abc"), M("c")],
+                vec![C("a"), C("b"), C("c")]);
+    test_unamb!(unambiguous10,
+                vec![M("Mo'"), M("Mu'"), M("Mo"), M("Mu")],
+                vec![C("Mo"), C("Mu")]);
+    test_unamb!(unambiguous11,
+                vec![M("zazb"), M("azb")], vec![C("a"), C("z")]);
+    test_unamb!(unambiguous12, vec![M("foo"), C("foo")], vec![C("foo")]);
+    test_unamb!(unambiguous13,
+                vec![M("ABCX"), M("CDAX"), M("BCX")],
+                vec![C("A"), C("BCX"), C("CD")]);
+    test_unamb!(unambiguous14,
+                vec![M("IMGX"), M("MVIX"), M("MGX"), M("DSX")],
+                vec![M("DSX"), C("I"), C("MGX"), C("MV")]);
+    test_unamb!(unambiguous15,
+                vec![M("IMG_"), M("MG_"), M("CIMG")],
+                vec![C("C"), C("I"), C("MG_")]);
+
+
+    // ************************************************************************
+    // Tests for suffix trimming.
+    // ************************************************************************
+    macro_rules! test_trim {
+        ($name:ident, $trim:expr, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|ul| {
+                        let cut = ul.is_cut();
+                        Literal { v: ul.v.into_bytes(), cut: cut }
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.trim_suffix($trim).unwrap();
+                assert_eq!($expected, escape_lits(got.literals()));
+            }
+        }
+    }
+
+    test_trim!(trim1, 1, vec![M("ab"), M("yz")], vec![C("a"), C("y")]);
+    test_trim!(trim2, 1, vec![M("abc"), M("abd")], vec![C("ab")]);
+    test_trim!(trim3, 2, vec![M("abc"), M("abd")], vec![C("a")]);
+    test_trim!(trim4, 2, vec![M("abc"), M("ghij")], vec![C("a"), C("gh")]);
+
+    // ************************************************************************
+    // Tests for longest common prefix.
+    // ************************************************************************
+
+    macro_rules! test_lcp {
+        ($name:ident, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|s: &str| Literal {
+                        v: s.to_owned().into_bytes(),
+                        cut: false,
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.longest_common_prefix();
+                assert_eq!($expected, escape_bytes(got));
+            }
+        };
+    }
+
+    test_lcp!(lcp1, vec!["a"], "a");
+    test_lcp!(lcp2, vec![], "");
+    test_lcp!(lcp3, vec!["a", "b"], "");
+    test_lcp!(lcp4, vec!["ab", "ab"], "ab");
+    test_lcp!(lcp5, vec!["ab", "a"], "a");
+    test_lcp!(lcp6, vec!["a", "ab"], "a");
+    test_lcp!(lcp7, vec!["ab", "b"], "");
+    test_lcp!(lcp8, vec!["b", "ab"], "");
+    test_lcp!(lcp9, vec!["foobar", "foobaz"], "fooba");
+    test_lcp!(lcp10, vec!["foobar", "foobaz", "a"], "");
+    test_lcp!(lcp11, vec!["a", "foobar", "foobaz"], "");
+    test_lcp!(lcp12, vec!["foo", "flub", "flab", "floo"], "f");
+
+    // ************************************************************************
+    // Tests for longest common suffix.
+    // ************************************************************************
+
+    macro_rules! test_lcs {
+        ($name:ident, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|s: &str| Literal {
+                        v: s.to_owned().into_bytes(),
+                        cut: false,
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.longest_common_suffix();
+                assert_eq!($expected, escape_bytes(got));
+            }
+        };
+    }
+
+    test_lcs!(lcs1, vec!["a"], "a");
+    test_lcs!(lcs2, vec![], "");
+    test_lcs!(lcs3, vec!["a", "b"], "");
+    test_lcs!(lcs4, vec!["ab", "ab"], "ab");
+    test_lcs!(lcs5, vec!["ab", "a"], "");
+    test_lcs!(lcs6, vec!["a", "ab"], "");
+    test_lcs!(lcs7, vec!["ab", "b"], "b");
+    test_lcs!(lcs8, vec!["b", "ab"], "b");
+    test_lcs!(lcs9, vec!["barfoo", "bazfoo"], "foo");
+    test_lcs!(lcs10, vec!["barfoo", "bazfoo", "a"], "");
+    test_lcs!(lcs11, vec!["a", "barfoo", "bazfoo"], "");
+    test_lcs!(lcs12, vec!["flub", "bub", "boob", "dub"], "b");
+}
diff --git a/rustc_deps/vendor/regex-syntax/src/hir/mod.rs b/rustc_deps/vendor/regex-syntax/src/hir/mod.rs
new file mode 100644
index 0000000..903e608
--- /dev/null
+++ b/rustc_deps/vendor/regex-syntax/src/hir/mod.rs
@@ -0,0 +1,2055 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Defines a high-level intermediate representation for regular expressions.
+*/
+use std::char;
+use std::cmp;
+use std::error;
+use std::fmt;
+use std::u8;
+
+use ast::Span;
+use hir::interval::{Interval, IntervalSet, IntervalSetIter};
+use unicode;
+
+pub use hir::visitor::{Visitor, visit};
+
+mod interval;
+pub mod literal;
+pub mod print;
+pub mod translate;
+mod visitor;
+
+/// An error that can occur while translating an `Ast` to a `Hir`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Error {
+    /// The kind of error.
+    kind: ErrorKind,
+    /// The original pattern that the translator's Ast was parsed from. Every
+    /// span in an error is a valid range into this string.
+    pattern: String,
+    /// The span of this error, derived from the Ast given to the translator.
+    span: Span,
+}
+
+impl Error {
+    /// Return the type of this error.
+    pub fn kind(&self) -> &ErrorKind {
+        &self.kind
+    }
+
+    /// The original pattern string in which this error occurred.
+    ///
+    /// Every span reported by this error is reported in terms of this string.
+    pub fn pattern(&self) -> &str {
+        &self.pattern
+    }
+
+    /// Return the span at which this error occurred.
+    pub fn span(&self) -> &Span {
+        &self.span
+    }
+}
+
+/// The type of an error that occurred while building an `Hir`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ErrorKind {
+    /// This error occurs when a Unicode feature is used when Unicode
+    /// support is disabled. For example `(?-u:\pL)` would trigger this error.
+    UnicodeNotAllowed,
+    /// This error occurs when translating a pattern that could match a byte
+    /// sequence that isn't UTF-8 and `allow_invalid_utf8` was disabled.
+    InvalidUtf8,
+    /// This occurs when an unrecognized Unicode property name could not
+    /// be found.
+    UnicodePropertyNotFound,
+    /// This occurs when an unrecognized Unicode property value could not
+    /// be found.
+    UnicodePropertyValueNotFound,
+    /// This occurs when the translator attempts to construct a character class
+    /// that is empty.
+    ///
+    /// Note that this restriction in the translator may be removed in the
+    /// future.
+    EmptyClassNotAllowed,
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl ErrorKind {
+    fn description(&self) -> &str {
+        use self::ErrorKind::*;
+        match *self {
+            UnicodeNotAllowed => "Unicode not allowed here",
+            InvalidUtf8 => "pattern can match invalid UTF-8",
+            UnicodePropertyNotFound => "Unicode property not found",
+            UnicodePropertyValueNotFound => "Unicode property value not found",
+            EmptyClassNotAllowed => "empty character classes are not allowed",
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        self.kind.description()
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ::error::Formatter::from(self).fmt(f)
+    }
+}
+
+impl fmt::Display for ErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(self.description())
+    }
+}
+
+/// A high-level intermediate representation (HIR) for a regular expression.
+///
+/// The HIR of a regular expression represents an intermediate step between its
+/// abstract syntax (a structured description of the concrete syntax) and
+/// compiled byte codes. The purpose of HIR is to make regular expressions
+/// easier to analyze. In particular, the AST is much more complex than the
+/// HIR. For example, while an AST supports arbitrarily nested character
+/// classes, the HIR will flatten all nested classes into a single set. The HIR
+/// will also "compile away" every flag present in the concrete syntax. For
+/// example, users of HIR expressions never need to worry about case folding;
+/// it is handled automatically by the translator (e.g., by translating `(?i)A`
+/// to `[aA]`).
+///
+/// If the HIR was produced by a translator that disallows invalid UTF-8, then
+/// the HIR is guaranteed to match UTF-8 exclusively.
+///
+/// This type defines its own destructor that uses constant stack space and
+/// heap space proportional to the size of the HIR.
+///
+/// The specific type of an HIR expression can be accessed via its `kind`
+/// or `into_kind` methods. This extra level of indirection exists for two
+/// reasons:
+///
+/// 1. Construction of an HIR expression *must* use the constructor methods
+///    on this `Hir` type instead of building the `HirKind` values directly.
+///    This permits construction to enforce invariants like "concatenations
+///    always consist of two or more sub-expressions."
+/// 2. Every HIR expression contains attributes that are defined inductively,
+///    and can be computed cheaply during the construction process. For
+///    example, one such attribute is whether the expression must match at the
+///    beginning of the text.
+///
+/// Also, an `Hir`'s `fmt::Display` implementation prints an HIR as a regular
+/// expression pattern string, and uses constant stack space and heap space
+/// proportional to the size of the `Hir`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Hir {
+    /// The underlying HIR kind.
+    kind: HirKind,
+    /// Analysis info about this HIR, computed during construction.
+    info: HirInfo,
+}
+
+/// The kind of an arbitrary `Hir` expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum HirKind {
+    /// The empty regular expression, which matches everything, including the
+    /// empty string.
+    Empty,
+    /// A single literal character that matches exactly this character.
+    Literal(Literal),
+    /// A single character class that matches any of the characters in the
+    /// class. A class can either consist of Unicode scalar values as
+    /// characters, or it can use bytes.
+    Class(Class),
+    /// An anchor assertion. An anchor assertion match always has zero length.
+    Anchor(Anchor),
+    /// A word boundary assertion, which may or may not be Unicode aware. A
+    /// word boundary assertion match always has zero length.
+    WordBoundary(WordBoundary),
+    /// A repetition operation applied to a child expression.
+    Repetition(Repetition),
+    /// A possibly capturing group, which contains a child expression.
+    Group(Group),
+    /// A concatenation of expressions. A concatenation always has at least two
+    /// child expressions.
+    ///
+    /// A concatenation matches only if each of its child expression matches
+    /// one after the other.
+    Concat(Vec<Hir>),
+    /// An alternation of expressions. An alternation always has at least two
+    /// child expressions.
+    ///
+    /// An alternation matches only if at least one of its child expression
+    /// matches. If multiple expressions match, then the leftmost is preferred.
+    Alternation(Vec<Hir>),
+}
+
+impl Hir {
+    /// Returns a reference to the underlying HIR kind.
+    pub fn kind(&self) -> &HirKind {
+        &self.kind
+    }
+
+    /// Consumes ownership of this HIR expression and returns its underlying
+    /// `HirKind`.
+    pub fn into_kind(mut self) -> HirKind {
+        use std::mem;
+        mem::replace(&mut self.kind, HirKind::Empty)
+    }
+
+    /// Returns an empty HIR expression.
+    ///
+    /// An empty HIR expression always matches, including the empty string.
+    pub fn empty() -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(true);
+        info.set_all_assertions(true);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(true);
+        Hir {
+            kind: HirKind::Empty,
+            info: info,
+        }
+    }
+
+    /// Creates a literal HIR expression.
+    ///
+    /// If the given literal has a `Byte` variant with an ASCII byte, then this
+    /// method panics. This enforces the invariant that `Byte` variants are
+    /// only used to express matching of invalid UTF-8.
+    pub fn literal(lit: Literal) -> Hir {
+        if let Literal::Byte(b) = lit {
+            assert!(b > 0x7F);
+        }
+
+        let mut info = HirInfo::new();
+        info.set_always_utf8(lit.is_unicode());
+        info.set_all_assertions(false);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(false);
+        Hir {
+            kind: HirKind::Literal(lit),
+            info: info,
+        }
+    }
+
+    /// Creates a class HIR expression.
+    pub fn class(class: Class) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(class.is_always_utf8());
+        info.set_all_assertions(false);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(false);
+        Hir {
+            kind: HirKind::Class(class),
+            info: info,
+        }
+    }
+
+    /// Creates an anchor assertion HIR expression.
+    pub fn anchor(anchor: Anchor) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(true);
+        info.set_all_assertions(true);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(true);
+        if let Anchor::StartText = anchor {
+            info.set_anchored_start(true);
+            info.set_any_anchored_start(true);
+        }
+        if let Anchor::EndText = anchor {
+            info.set_anchored_end(true);
+            info.set_any_anchored_end(true);
+        }
+        Hir {
+            kind: HirKind::Anchor(anchor),
+            info: info,
+        }
+    }
+
+    /// Creates a word boundary assertion HIR expression.
+    pub fn word_boundary(word_boundary: WordBoundary) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(true);
+        info.set_all_assertions(true);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        // A negated word boundary matches the empty string, but a normal
+        // word boundary does not!
+        info.set_match_empty(word_boundary.is_negated());
+        // Negated ASCII word boundaries can match invalid UTF-8.
+        if let WordBoundary::AsciiNegate = word_boundary {
+            info.set_always_utf8(false);
+        }
+        Hir {
+            kind: HirKind::WordBoundary(word_boundary),
+            info: info,
+        }
+    }
+
+    /// Creates a repetition HIR expression.
+    pub fn repetition(rep: Repetition) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(rep.hir.is_always_utf8());
+        info.set_all_assertions(rep.hir.is_all_assertions());
+        // If this operator can match the empty string, then it can never
+        // be anchored.
+        info.set_anchored_start(
+            !rep.is_match_empty() && rep.hir.is_anchored_start()
+        );
+        info.set_anchored_end(
+            !rep.is_match_empty() && rep.hir.is_anchored_end()
+        );
+        info.set_any_anchored_start(rep.hir.is_any_anchored_start());
+        info.set_any_anchored_end(rep.hir.is_any_anchored_end());
+        info.set_match_empty(rep.is_match_empty() || rep.hir.is_match_empty());
+        Hir {
+            kind: HirKind::Repetition(rep),
+            info: info,
+        }
+    }
+
+    /// Creates a group HIR expression.
+    pub fn group(group: Group) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(group.hir.is_always_utf8());
+        info.set_all_assertions(group.hir.is_all_assertions());
+        info.set_anchored_start(group.hir.is_anchored_start());
+        info.set_anchored_end(group.hir.is_anchored_end());
+        info.set_any_anchored_start(group.hir.is_any_anchored_start());
+        info.set_any_anchored_end(group.hir.is_any_anchored_end());
+        info.set_match_empty(group.hir.is_match_empty());
+        Hir {
+            kind: HirKind::Group(group),
+            info: info,
+        }
+    }
+
+    /// Returns the concatenation of the given expressions.
+    ///
+    /// This flattens the concatenation as appropriate.
+    pub fn concat(mut exprs: Vec<Hir>) -> Hir {
+        match exprs.len() {
+            0 => Hir::empty(),
+            1 => exprs.pop().unwrap(),
+            _ => {
+                let mut info = HirInfo::new();
+                info.set_always_utf8(true);
+                info.set_all_assertions(true);
+                info.set_any_anchored_start(false);
+                info.set_any_anchored_end(false);
+                info.set_match_empty(true);
+
+                // Some attributes require analyzing all sub-expressions.
+                for e in &exprs {
+                    let x = info.is_always_utf8() && e.is_always_utf8();
+                    info.set_always_utf8(x);
+
+                    let x = info.is_all_assertions() && e.is_all_assertions();
+                    info.set_all_assertions(x);
+
+                    let x =
+                        info.is_any_anchored_start()
+                        || e.is_any_anchored_start();
+                    info.set_any_anchored_start(x);
+
+                    let x =
+                        info.is_any_anchored_end()
+                        || e.is_any_anchored_end();
+                    info.set_any_anchored_end(x);
+
+                    let x = info.is_match_empty() && e.is_match_empty();
+                    info.set_match_empty(x);
+                }
+                // Anchored attributes require something slightly more
+                // sophisticated. Normally, WLOG, to determine whether an
+                // expression is anchored to the start, we'd only need to check
+                // the first expression of a concatenation. However,
+                // expressions like `$\b^` are still anchored to the start,
+                // but the first expression in the concatenation *isn't*
+                // anchored to the start. So the "first" expression to look at
+                // is actually one that is either not an assertion or is
+                // specifically the StartText assertion.
+                info.set_anchored_start(
+                    exprs.iter()
+                        .take_while(|e| {
+                            e.is_anchored_start() || e.is_all_assertions()
+                        })
+                        .any(|e| {
+                            e.is_anchored_start()
+                        }));
+                // Similarly for the end anchor, but in reverse.
+                info.set_anchored_end(
+                    exprs.iter()
+                        .rev()
+                        .take_while(|e| {
+                            e.is_anchored_end() || e.is_all_assertions()
+                        })
+                        .any(|e| {
+                            e.is_anchored_end()
+                        }));
+                Hir {
+                    kind: HirKind::Concat(exprs),
+                    info: info,
+                }
+            }
+        }
+    }
+
+    /// Returns the alternation of the given expressions.
+    ///
+    /// This flattens the alternation as appropriate.
+    pub fn alternation(mut exprs: Vec<Hir>) -> Hir {
+        match exprs.len() {
+            0 => Hir::empty(),
+            1 => exprs.pop().unwrap(),
+            _ => {
+                let mut info = HirInfo::new();
+                info.set_always_utf8(true);
+                info.set_all_assertions(true);
+                info.set_anchored_start(true);
+                info.set_anchored_end(true);
+                info.set_any_anchored_start(false);
+                info.set_any_anchored_end(false);
+                info.set_match_empty(false);
+
+                // Some attributes require analyzing all sub-expressions.
+                for e in &exprs {
+                    let x = info.is_always_utf8() && e.is_always_utf8();
+                    info.set_always_utf8(x);
+
+                    let x = info.is_all_assertions() && e.is_all_assertions();
+                    info.set_all_assertions(x);
+
+                    let x = info.is_anchored_start() && e.is_anchored_start();
+                    info.set_anchored_start(x);
+
+                    let x = info.is_anchored_end() && e.is_anchored_end();
+                    info.set_anchored_end(x);
+
+                    let x =
+                        info.is_any_anchored_start()
+                        || e.is_any_anchored_start();
+                    info.set_any_anchored_start(x);
+
+                    let x =
+                        info.is_any_anchored_end()
+                        || e.is_any_anchored_end();
+                    info.set_any_anchored_end(x);
+
+                    let x = info.is_match_empty() || e.is_match_empty();
+                    info.set_match_empty(x);
+                }
+                Hir {
+                    kind: HirKind::Alternation(exprs),
+                    info: info,
+                }
+            }
+        }
+    }
+
+    /// Build an HIR expression for `.`.
+    ///
+    /// A `.` expression matches any character except for `\n`. To build an
+    /// expression that matches any character, including `\n`, use the `any`
+    /// method.
+    ///
+    /// If `bytes` is `true`, then this assumes characters are limited to a
+    /// single byte.
+    pub fn dot(bytes: bool) -> Hir {
+        if bytes {
+            let mut cls = ClassBytes::empty();
+            cls.push(ClassBytesRange::new(b'\0', b'\x09'));
+            cls.push(ClassBytesRange::new(b'\x0B', b'\xFF'));
+            Hir::class(Class::Bytes(cls))
+        } else {
+            let mut cls = ClassUnicode::empty();
+            cls.push(ClassUnicodeRange::new('\0', '\x09'));
+            cls.push(ClassUnicodeRange::new('\x0B', '\u{10FFFF}'));
+            Hir::class(Class::Unicode(cls))
+        }
+    }
+
+    /// Build an HIR expression for `(?s).`.
+    ///
+    /// A `(?s).` expression matches any character, including `\n`. To build an
+    /// expression that matches any character except for `\n`, then use the
+    /// `dot` method.
+    ///
+    /// If `bytes` is `true`, then this assumes characters are limited to a
+    /// single byte.
+    pub fn any(bytes: bool) -> Hir {
+        if bytes {
+            let mut cls = ClassBytes::empty();
+            cls.push(ClassBytesRange::new(b'\0', b'\xFF'));
+            Hir::class(Class::Bytes(cls))
+        } else {
+            let mut cls = ClassUnicode::empty();
+            cls.push(ClassUnicodeRange::new('\0', '\u{10FFFF}'));
+            Hir::class(Class::Unicode(cls))
+        }
+    }
+
+    /// Return true if and only if this HIR will always match valid UTF-8.
+    ///
+    /// When this returns false, then it is possible for this HIR expression
+    /// to match invalid UTF-8.
+    pub fn is_always_utf8(&self) -> bool {
+        self.info.is_always_utf8()
+    }
+
+    /// Returns true if and only if this entire HIR expression is made up of
+    /// zero-width assertions.
+    ///
+    /// This includes expressions like `^$\b\A\z` and even `((\b)+())*^`, but
+    /// not `^a`.
+    pub fn is_all_assertions(&self) -> bool {
+        self.info.is_all_assertions()
+    }
+
+    /// Return true if and only if this HIR is required to match from the
+    /// beginning of text. This includes expressions like `^foo`, `^(foo|bar)`,
+    /// `^foo|^bar` but not `^foo|bar`.
+    pub fn is_anchored_start(&self) -> bool {
+        self.info.is_anchored_start()
+    }
+
+    /// Return true if and only if this HIR is required to match at the end
+    /// of text. This includes expressions like `foo$`, `(foo|bar)$`,
+    /// `foo$|bar$` but not `foo$|bar`.
+    pub fn is_anchored_end(&self) -> bool {
+        self.info.is_anchored_end()
+    }
+
+    /// Return true if and only if this HIR contains any sub-expression that
+    /// is required to match at the beginning of text. Specifically, this
+    /// returns true if the `^` symbol (when multiline mode is disabled) or the
+    /// `\A` escape appear anywhere in the regex.
+    pub fn is_any_anchored_start(&self) -> bool {
+        self.info.is_any_anchored_start()
+    }
+
+    /// Return true if and only if this HIR contains any sub-expression that is
+    /// required to match at the end of text. Specifically, this returns true
+    /// if the `$` symbol (when multiline mode is disabled) or the `\z` escape
+    /// appear anywhere in the regex.
+    pub fn is_any_anchored_end(&self) -> bool {
+        self.info.is_any_anchored_end()
+    }
+
+    /// Return true if and only if the empty string is part of the language
+    /// matched by this regular expression.
+    ///
+    /// This includes `a*`, `a?b*`, `a{0}`, `()`, `()+`, `^$`, `a|b?`, `\B`,
+    /// but not `a`, `a+` or `\b`.
+    pub fn is_match_empty(&self) -> bool {
+        self.info.is_match_empty()
+    }
+}
+
+impl HirKind {
+    /// Return true if and only if this HIR is the empty regular expression.
+    ///
+    /// Note that this is not defined inductively. That is, it only tests if
+    /// this kind is the `Empty` variant. To get the inductive definition,
+    /// use the `is_match_empty` method on [`Hir`](struct.Hir.html).
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            HirKind::Empty => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if this kind has any (including possibly
+    /// empty) subexpressions.
+    pub fn has_subexprs(&self) -> bool {
+        match *self {
+            HirKind::Empty
+            | HirKind::Literal(_)
+            | HirKind::Class(_)
+            | HirKind::Anchor(_)
+            | HirKind::WordBoundary(_) => false,
+            HirKind::Group(_)
+            | HirKind::Repetition(_)
+            | HirKind::Concat(_)
+            | HirKind::Alternation(_) => true,
+        }
+    }
+}
+
+/// Print a display representation of this Hir.
+///
+/// The result of this is a valid regular expression pattern string.
+///
+/// This implementation uses constant stack space and heap space proportional
+/// to the size of the `Hir`.
+impl fmt::Display for Hir {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use hir::print::Printer;
+        Printer::new().print(self, f)
+    }
+}
+
+/// The high-level intermediate representation of a literal.
+///
+/// A literal corresponds to a single character, where a character is either
+/// defined by a Unicode scalar value or an arbitrary byte. Unicode characters
+/// are preferred whenever possible. In particular, a `Byte` variant is only
+/// ever produced when it could match invalid UTF-8.
+#[derive(Clone, Debug, Eq, PartialEq)]