lib_ruby_parser_ast/traverse/finder/pattern/mod.rs
1mod item;
2pub use item::Item;
3
4mod error;
5pub use error::PatternError;
6
7/// Pattern that is used for matching.
8///
9/// Consists of multiple `finder::Item` elements
10///
11/// For example the following pattern:
12///
13/// ```text
14/// Pattern::new("args -> arglist -> 2 -> default")
15/// ```
16///
17/// can find a node that represents constant `FIND_ME` in the following code:
18///
19/// ```text
20/// def foo(a, b, c = FIND_ME)
21/// end
22/// ```
23///
24/// It means:
25/// 1. enter `.args` of the `Def` node (`(a, b, c = FIND_ME`))
26/// 2. enter its `.argslist` (`a, b, c = FIND_ME`)
27/// 3. enter element `[2]` (`c = FIND_ME`)
28/// 4. enter `.default` of the `Optarg` node (`FIND_ME`)
29#[derive(Debug, PartialEq, Eq)]
30pub struct Pattern {
31 pub(crate) parts: Vec<Item>,
32}
33
34impl Pattern {
35 /// Constructs a pattern from a string, returns an error on the first sub-pattern error
36 pub fn new(input: &str) -> Result<Self, PatternError> {
37 let mut parts: Vec<Item> = vec![];
38
39 for part in input.split(" -> ") {
40 let part = Item::new(part)?;
41 parts.push(part);
42 }
43
44 Ok(Self { parts })
45 }
46
47 /// Returns `true` if pattern is empty
48 pub fn empty() -> Self {
49 Self { parts: vec![] }
50 }
51
52 /// Pushes a new `Item` into a pattern
53 pub fn push(&mut self, item: Item) {
54 self.parts.push(item)
55 }
56
57 /// Pops an `Item` from a pattern
58 pub fn pop(&mut self) -> Option<Item> {
59 self.parts.pop()
60 }
61
62 pub(crate) fn unshift(&mut self) -> Option<Item> {
63 if self.parts.is_empty() {
64 None
65 } else {
66 Some(self.parts.remove(0))
67 }
68 }
69}