harper_core/expr/
sequence_expr.rs1use paste::paste;
2
3use crate::{
4 Span, Token, TokenKind,
5 patterns::{AnyPattern, IndefiniteArticle, WhitespacePattern, Word},
6};
7
8use super::{Expr, Optional, Repeating, Step, UnlessStep};
9
10#[derive(Default)]
11pub struct SequenceExpr {
12 exprs: Vec<Box<dyn Expr>>,
13}
14
15macro_rules! gen_then_from_is {
17 ($quality:ident) => {
18 paste! {
19 #[doc = concat!("Adds a step matching a token where [`TokenKind::is_", stringify!($quality), "()`] returns true.")]
20 pub fn [< then_$quality >] (self) -> Self{
21 self.then(|tok: &Token, _source: &[char]| {
22 tok.kind.[< is_$quality >]()
23 })
24 }
25
26 #[doc = concat!("Adds an optional step matching a token where [`TokenKind::is_", stringify!($quality), "()`] returns true.")]
27 pub fn [< then_optional_$quality >] (self) -> Self{
28 self.then_optional(|tok: &Token, _source: &[char]| {
29 tok.kind.[< is_$quality >]()
30 })
31 }
32
33 #[doc = concat!("Adds a step matching one or more consecutive tokens where [`TokenKind::is_", stringify!($quality), "()`] returns true.")]
34 pub fn [< then_one_or_more_$quality s >] (self) -> Self{
35 self.then_one_or_more(Box::new(|tok: &Token, _source: &[char]| {
36 tok.kind.[< is_$quality >]()
37 }))
38 }
39
40 #[doc = concat!("Adds a step matching a token where [`TokenKind::is_", stringify!($quality), "()`] returns false.")]
41 pub fn [< then_anything_but_$quality >] (self) -> Self{
42 self.then(|tok: &Token, _source: &[char]| {
43 if tok.kind.[< is_$quality >](){
44 false
45 }else{
46 true
47 }
48 })
49 }
50 }
51 };
52}
53
54impl Expr for SequenceExpr {
55 fn run(&self, mut cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span> {
59 let mut window = Span::new_with_len(cursor, 0);
60
61 for cur_expr in &self.exprs {
62 let out = cur_expr.run(cursor, tokens, source)?;
63
64 if out.end > out.start {
66 window.expand_to_include(out.start);
67 window.expand_to_include(out.end.checked_sub(1).unwrap_or(out.start));
68 }
69
70 if out.end > cursor {
72 cursor = out.end;
73 } else if out.start < cursor {
74 cursor = out.start;
75 }
76 }
78
79 Some(window)
80 }
81}
82
83impl SequenceExpr {
84 pub fn any_capitalization_of(word: &'static str) -> Self {
88 Self::default().then_any_capitalization_of(word)
89 }
90
91 pub fn aco(word: &'static str) -> Self {
93 Self::any_capitalization_of(word)
94 }
95
96 pub fn then(mut self, expr: impl Expr + 'static) -> Self {
100 self.exprs.push(Box::new(expr));
101 self
102 }
103
104 pub fn then_optional(mut self, expr: impl Expr + 'static) -> Self {
106 self.exprs.push(Box::new(Optional::new(expr)));
107 self
108 }
109
110 pub fn then_seq(mut self, mut other: Self) -> Self {
113 self.exprs.append(&mut other.exprs);
114 self
115 }
116
117 pub fn then_strict(self, kind: TokenKind) -> Self {
119 self.then(move |tok: &Token, _source: &[char]| tok.kind == kind)
120 }
121
122 pub fn then_whitespace(self) -> Self {
124 self.then(WhitespacePattern)
125 }
126
127 pub fn t_ws(self) -> Self {
129 self.then_whitespace()
130 }
131
132 pub fn then_one_or_more(self, expr: impl Expr + 'static) -> Self {
133 self.then(Repeating::new(Box::new(expr), 1))
134 }
135
136 pub fn then_unless(self, condition: impl Expr + 'static) -> Self {
143 self.then(UnlessStep::new(condition, |_tok: &Token, _src: &[char]| {
144 true
145 }))
146 }
147
148 pub fn then_anything(self) -> Self {
152 self.then(AnyPattern)
153 }
154
155 pub fn t_any(self) -> Self {
159 self.then_anything()
160 }
161
162 pub fn then_any_word(self) -> Self {
166 self.then(|tok: &Token, _source: &[char]| tok.kind.is_word())
167 }
168
169 pub fn then_any_capitalization_of(self, word: &'static str) -> Self {
171 self.then(Word::new(word))
172 }
173
174 pub fn t_aco(self, word: &'static str) -> Self {
176 self.then_any_capitalization_of(word)
177 }
178
179 pub fn then_exact_word(self, word: &'static str) -> Self {
181 self.then(Word::new_exact(word))
182 }
183
184 gen_then_from_is!(nominal);
189 gen_then_from_is!(plural_nominal);
190 gen_then_from_is!(non_plural_nominal);
191 gen_then_from_is!(possessive_nominal);
192
193 gen_then_from_is!(noun);
196 gen_then_from_is!(proper_noun);
197 gen_then_from_is!(mass_noun_only);
198
199 gen_then_from_is!(pronoun);
202 gen_then_from_is!(first_person_singular_pronoun);
203 gen_then_from_is!(first_person_plural_pronoun);
204 gen_then_from_is!(second_person_pronoun);
205 gen_then_from_is!(third_person_pronoun);
206 gen_then_from_is!(third_person_singular_pronoun);
207 gen_then_from_is!(third_person_plural_pronoun);
208
209 gen_then_from_is!(verb);
213 gen_then_from_is!(auxiliary_verb);
214 gen_then_from_is!(linking_verb);
215
216 gen_then_from_is!(adjective);
219 gen_then_from_is!(adverb);
220
221 gen_then_from_is!(determiner);
224
225 pub fn then_indefinite_article(self) -> Self {
227 self.then(IndefiniteArticle::default())
228 }
229
230 gen_then_from_is!(conjunction);
233 gen_then_from_is!(preposition);
234
235 gen_then_from_is!(punctuation);
238 gen_then_from_is!(apostrophe);
239 gen_then_from_is!(comma);
240 gen_then_from_is!(hyphen);
241 gen_then_from_is!(period);
242 gen_then_from_is!(semicolon);
243
244 gen_then_from_is!(number);
247 gen_then_from_is!(case_separator);
248}
249
250impl<S> From<S> for SequenceExpr
251where
252 S: Step + 'static,
253{
254 fn from(step: S) -> Self {
255 Self {
256 exprs: vec![Box::new(step)],
257 }
258 }
259}