filecheck/lib.rs
1//! This crate provides a text pattern matching library with functionality similar to the LLVM
2//! project's [FileCheck command](https://llvm.org/docs/CommandGuide/FileCheck.html).
3//!
4//! A list of directives is typically extracted from a file containing a test case. The test case
5//! is then run through the program under test, and its output matched against the directives.
6//!
7//! See the [`CheckerBuilder`](struct.CheckerBuilder.html) and [`Checker`](struct.Checker.html)
8//! types for the main library API.
9//!
10//! # Directives
11//!
12//! These are the directives recognized by *filecheck*:
13//!
14//! <pre class="rust">
15//! <a href="#the-check-directive">check: <i><pattern></i></a>
16//! <a href="#the-sameln-directive">sameln: <i><pattern></i></a>
17//! <a href="#the-nextln-directive">nextln: <i><pattern></i></a>
18//! <a href="#the-unordered-directive">unordered: <i><pattern></i></a>
19//! <a href="#the-not-directive">not: <i><pattern></i></a>
20//! <a href="#the-regex-directive">regex: <i><variable></i>=<i><regex></i></a>
21//! </pre>
22//!
23//! Each directive is described in more detail below.
24//!
25//! ## Example
26//!
27//! The Rust program below prints the primes less than 100. It has *filecheck* directives embedded
28//! in comments:
29//!
30//! ```rust
31//! fn is_prime(x: u32) -> bool {
32//! (2..x).all(|d| x % d != 0)
33//! }
34//!
35//! // Check that we get the primes and nothing else:
36//! // regex: NUM=\d+
37//! // not: $NUM
38//! // check: 2
39//! // nextln: 3
40//! // check: 89
41//! // nextln: 97
42//! // not: $NUM
43//! fn main() {
44//! for p in (2..10).filter(|&x| is_prime(x)) {
45//! println!("{}", p);
46//! }
47//! }
48//! ```
49//!
50//! A test driver compiles and runs the program, then pipes the output through *filecheck*:
51//!
52//! ```sh
53//! $ rustc primes.rs
54//! $ ./primes | clif-util filecheck -v
55//! #0 regex: NUM=\d+
56//! #1 not: $NUM
57//! #2 check: 2
58//! #3 nextln: 3
59//! #4 check: 89
60//! #5 nextln: 97
61//! #6 not: $NUM
62//! no match #1: \d+
63//! > 2
64//! ~
65//! match #2: \b2\b
66//! > 3
67//! ~
68//! match #3: \b3\b
69//! > 5
70//! > 7
71//! ...
72//! > 79
73//! > 83
74//! > 89
75//! ~~
76//! match #4: \b89\b
77//! > 97
78//! ~~
79//! match #5: \b97\b
80//! no match #6: \d+
81//! OK
82//! ```
83//!
84//! ## The `check:` directive
85//!
86//! Match patterns non-overlapping and in order:
87//!
88//! ```sh
89//! #0 check: one
90//! #1 check: two
91//! ```
92//!
93//! These directives will match the string `"one two"`, but not `"two one"`. The second directive
94//! must match after the first one, and it can't overlap.
95//!
96//! ## The `sameln:` directive
97//!
98//! Match a pattern in the same line as the previous match.
99//!
100//! ```sh
101//! #0 check: one
102//! #1 sameln: two
103//! ```
104//!
105//! These directives will match the string `"one two"`, but not `"one\ntwo"`. The second match must
106//! be in the same line as the first. Like the `check:` directive, the match must also follow the
107//! first match, so `"two one" would not be matched.
108//!
109//! If there is no previous match, `sameln:` matches on the first line of the input.
110//!
111//! ## The `nextln:` directive
112//!
113//! Match a pattern in the next line after the previous match.
114//!
115//! ```sh
116//! #0 check: one
117//! #1 nextln: two
118//! ```
119//!
120//! These directives will match the string `"one\ntwo"`, but not `"one two"` or `"one\n\ntwo"`.
121//!
122//! If there is no previous match, `nextln:` matches on the second line of the input as if there
123//! were a previous match on the first line.
124//!
125//! ## The `unordered:` directive
126//!
127//! Match patterns in any order, and possibly overlapping each other.
128//!
129//! ```sh
130//! #0 unordered: one
131//! #1 unordered: two
132//! ```
133//!
134//! These directives will match the string `"one two"` *and* the string `"two one"`.
135//!
136//! When a normal ordered match is inserted into a sequence of `unordered:` directives, it acts as
137//! a barrier:
138//!
139//! ```sh
140//! #0 unordered: one
141//! #1 unordered: two
142//! #2 check: three
143//! #3 unordered: four
144//! #4 unordered: five
145//! ```
146//!
147//! These directives will match `"two one three four five"`, but not `"two three one four five"`.
148//! The `unordered:` matches are not allowed to cross the ordered `check:` directive.
149//!
150//! When `unordered:` matches define and use variables, a topological order is enforced. This means
151//! that a match referencing a variable must follow the match where the variable was defined:
152//!
153//! ```sh
154//! #0 regex: V=\bv\d+\b
155//! #1 unordered: $(va=$V) = load
156//! #2 unordered: $(vb=$V) = iadd $va
157//! #3 unordered: $(vc=$V) = load
158//! #4 unordered: iadd $va, $vc
159//! ```
160//!
161//! In the above directives, #2 must match after #1, and #4 must match after both #1 and #3, but
162//! otherwise they can match in any order.
163//!
164//! ## The `not:` directive
165//!
166//! Check that a pattern *does not* appear between matches.
167//!
168//! ```sh
169//! #0 check: one
170//! #1 not: two
171//! #2 check: three
172//! ```
173//!
174//! The directives above will match `"one five three"`, but not `"one two three"`.
175//!
176//! The pattern in a `not:` directive can't define any variables. Since it never matches anything,
177//! the variables would not get a value.
178//!
179//! ## The `regex:` directive
180//!
181//! Define a shorthand name for a regular expression.
182//!
183//! ```sh
184//! #0 regex: ID=\b[_a-zA-Z][_0-9a-zA-Z]*\b
185//! #1 check: $ID + $ID
186//! ```
187//!
188//! The `regex:` directive gives a name to a regular expression which can then be used as part of a
189//! pattern to match. Patterns are otherwise just plain text strings to match, so this is not
190//! simple macro expansion.
191//!
192//! See [the Rust regex crate](../regex/index.html#syntax) for the regular expression syntax.
193//!
194//! # Patterns and variables
195//!
196//! Patterns are plain text strings to be matched in the input file. The dollar sign is used as an
197//! escape character to expand variables. The following escape sequences are recognized:
198//!
199//! <pre>
200//! $$ Match single dollar sign.
201//! $() Match the empty string.
202//! $(=<i><regex></i>) Match regular expression <i><regex></i>.
203//! $<i><var></i> Match contents of variable <i><var></i>.
204//! $(<i><var></i>) Match contents of variable <i><var></i>.
205//! $(<i><var></i>=<i><regex></i>) Match <i><regex></i>, then
206//! define <i><var></i> as the matched text.
207//! $(<i><var></i>=$<i><rxvar></i>) Match regex in <i><rxvar></i>, then
208//! define <i><var></i> as the matched text.
209//! </pre>
210//!
211//! Variables can contain either plain text or regular expressions. Plain text variables are
212//! defined with the `$(var=...)` syntax in a previous directive. They match the same text again.
213//! Backreferences within the same pattern are not allowed. When a variable is defined in a
214//! pattern, it can't be referenced again in the same pattern.
215//!
216//! Regular expression variables are defined with the `regex:` directive. They match the regular
217//! expression each time they are used, so the matches don't need to be identical.
218//!
219//! ## Word boundaries
220//!
221//! If a pattern begins or ends with a (plain text) letter or number, it will only match on a word
222//! boundary. Use the `$()` empty string match to prevent this:
223//!
224//! ```sh
225//! check: one$()
226//! ```
227//!
228//! This will match `"one"` and `"onetwo"`, but not `"zeroone"`.
229//!
230//! The empty match syntax can also be used to require leading or trailing whitespace:
231//!
232//! ```sh
233//! check: one, $()
234//! ```
235//!
236//! This will match `"one, two"` , but not `"one,two"`. Without the `$()`, trailing whitespace
237//! would be trimmed from the pattern.
238
239#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
240
241pub use checker::{Checker, CheckerBuilder};
242pub use error::{Error, Result};
243pub use variable::{Value, VariableMap, NO_VARIABLES};
244
245mod checker;
246mod error;
247mod explain;
248mod pattern;
249mod variable;
250
251/// The range of a match in the input text.
252pub type MatchRange = (usize, usize);