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