1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! Query-clause parsing: turning a raw query string into bare terms,
//! quoted phrases and `word*` prefixes.
//!
//! Split out of `segment_phrase` in v6. That file had reached exactly the
//! 500-line ceiling, and the two halves were never one job: everything
//! above it matches phrases against a segment's stored positions, while
//! this half never touches a segment at all — it reads bytes and produces
//! clauses, and its only dependency is the tokenizer.
use cratetokenize;
/// Parsed query clauses: bare terms, phrases (each a token sequence) and
/// prefix stems.
pub type Clauses = ;
/// Split a query into bare terms, quoted phrases, and `word*` prefixes.
/// A `"…"` group of two or more tokens is a phrase (a shorter group joins
/// the bare terms — a one-word "phrase" is just that word); an unquoted
/// word ending in `*` is a prefix. An unterminated quote is lenient: the
/// remainder is read as plain text rather than rejected.
///
/// # Examples
///
/// The three clause kinds come back separated: bare terms, quoted phrases,
/// and `*`-suffixed prefixes.
///
/// ```
/// let (terms, phrases, prefixes) =
/// kevy_text::parse_clauses(br#"alpha "two words" beta*"#);
/// assert_eq!(terms, vec![b"alpha".to_vec()]);
/// assert_eq!(phrases, vec![vec![b"two".to_vec(), b"words".to_vec()]]);
/// assert_eq!(prefixes, vec![b"beta".to_vec()]);
/// ```
///
/// A one-word "phrase" is not a phrase — it joins the bare terms, because a
/// phrase of one word is that word.
///
/// ```
/// let (terms, phrases, _) = kevy_text::parse_clauses(br#""solo""#);
/// assert_eq!(terms, vec![b"solo".to_vec()]);
/// assert!(phrases.is_empty());
/// ```
///
/// An unterminated quote is read as plain text rather than refused.
///
/// ```
/// let (terms, phrases, _) = kevy_text::parse_clauses(br#"open "never closed"#);
/// assert!(phrases.is_empty());
/// assert!(terms.contains(&b"open".to_vec()));
/// ```
/// Split plain (unquoted) query text: a whitespace word ending in `*`
/// becomes a prefix clause (its stem, ASCII-lowercased to match the
/// stored token form), every other word tokenizes into bare terms.