1mod all;
17mod anchor_end;
18mod anchor_start;
19mod expr_map;
20mod first_match_of;
21mod fixed_phrase;
22mod longest_match_of;
23mod mergeable_words;
24mod optional;
25mod reflexive_pronoun;
26mod repeating;
27mod sequence_expr;
28mod similar_to_phrase;
29mod space_or_hyphen;
30mod spelled_number_expr;
31mod step;
32mod time_unit_expr;
33mod unless_step;
34mod word_expr_group;
35
36#[cfg(not(feature = "concurrent"))]
37use std::rc::Rc;
38use std::sync::Arc;
39
40pub use all::All;
41pub use anchor_end::AnchorEnd;
42pub use anchor_start::AnchorStart;
43pub use expr_map::ExprMap;
44pub use first_match_of::FirstMatchOf;
45pub use fixed_phrase::FixedPhrase;
46pub use longest_match_of::LongestMatchOf;
47pub use mergeable_words::MergeableWords;
48pub use optional::Optional;
49pub use reflexive_pronoun::ReflexivePronoun;
50pub use repeating::Repeating;
51pub use sequence_expr::SequenceExpr;
52pub use similar_to_phrase::SimilarToPhrase;
53pub use space_or_hyphen::SpaceOrHyphen;
54pub use spelled_number_expr::SpelledNumberExpr;
55pub use step::Step;
56pub use time_unit_expr::TimeUnitExpr;
57pub use unless_step::UnlessStep;
58pub use word_expr_group::WordExprGroup;
59
60use crate::{Document, LSend, Span, Token};
61
62pub trait Expr: LSend {
63 fn run(&self, cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span>;
64}
65
66impl<S> Expr for S
67where
68 S: Step + ?Sized,
69{
70 fn run(&self, cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span> {
71 self.step(tokens, cursor, source).map(|s| {
72 if s >= 0 {
73 Span::new_with_len(cursor, s as usize)
74 } else {
75 Span::new(add(cursor, s).unwrap(), cursor)
76 }
77 })
78 }
79}
80
81impl<E> Expr for Arc<E>
82where
83 E: Expr,
84{
85 fn run(&self, cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span> {
86 self.as_ref().run(cursor, tokens, source)
87 }
88}
89
90#[cfg(not(feature = "concurrent"))]
91impl<E> Expr for Rc<E>
92where
93 E: Expr,
94{
95 fn run(&self, cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span> {
96 self.as_ref().run(cursor, tokens, source)
97 }
98}
99
100fn add(u: usize, i: isize) -> Option<usize> {
101 if i.is_negative() {
102 u.checked_sub(i.wrapping_abs() as u32 as usize)
103 } else {
104 u.checked_add(i as usize)
105 }
106}
107
108pub trait ExprExt {
109 fn iter_matches<'a>(
112 &'a self,
113 tokens: &'a [Token],
114 source: &'a [char],
115 ) -> Box<dyn Iterator<Item = Span> + 'a>;
116
117 fn iter_matches_in_doc<'a>(&'a self, doc: &'a Document) -> Box<dyn Iterator<Item = Span> + 'a>;
118}
119
120impl<E: ?Sized> ExprExt for E
121where
122 E: Expr,
123{
124 fn iter_matches<'a>(
125 &'a self,
126 tokens: &'a [Token],
127 source: &'a [char],
128 ) -> Box<(dyn Iterator<Item = Span> + 'a)> {
129 let mut last_end = 0usize;
130
131 Box::new((0..tokens.len()).filter_map(move |i| {
132 let span = self.run(i, tokens, source)?;
133 if span.start >= last_end {
134 last_end = span.end;
135 Some(span)
136 } else {
137 None
138 }
139 }))
140 }
141
142 fn iter_matches_in_doc<'a>(
143 &'a self,
144 doc: &'a Document,
145 ) -> Box<(dyn Iterator<Item = Span> + 'a)> {
146 Box::new(self.iter_matches(doc.get_tokens(), doc.get_source()))
147 }
148}
149
150pub trait OwnedExprExt {
151 fn or(self, other: impl Expr + 'static) -> LongestMatchOf;
152}
153
154impl<E> OwnedExprExt for E
155where
156 E: Expr + 'static,
157{
158 fn or(self, other: impl Expr + 'static) -> LongestMatchOf {
159 LongestMatchOf::new(vec![Box::new(self), Box::new(other)])
160 }
161}