grit_pattern_matcher/pattern/
before.rs

1use super::{
2    patterns::{Matcher, Pattern, PatternName},
3    resolved_pattern::ResolvedPattern,
4    State,
5};
6use crate::{
7    binding::Binding,
8    context::{ExecContext, QueryContext},
9    errors::debug,
10};
11use grit_util::{
12    error::{GritPatternError, GritResult},
13    AnalysisLogs, AstNode,
14};
15
16#[derive(Debug, Clone)]
17pub struct Before<Q: QueryContext> {
18    pub before: Pattern<Q>,
19}
20
21impl<Q: QueryContext> Before<Q> {
22    pub fn new(before: Pattern<Q>) -> Self {
23        Self { before }
24    }
25
26    pub fn prev_pattern<'a>(
27        &'a self,
28        state: &mut State<'a, Q>,
29        context: &'a Q::ExecContext<'a>,
30        logs: &mut AnalysisLogs,
31    ) -> GritResult<Q::ResolvedPattern<'a>> {
32        let binding = Q::Binding::from_pattern(&self.before, state, context, logs)?;
33        let Some(node) = binding.as_node() else {
34            return Err(GritPatternError::new(
35                "cannot get the node before this binding",
36            ));
37        };
38
39        if let Some(prev) = node.previous_named_node() {
40            Ok(ResolvedPattern::from_node_binding(prev))
41        } else {
42            debug(
43                logs,
44                state,
45                context.language(),
46                "no node before current node, treating as undefined",
47            )?;
48            Ok(Q::ResolvedPattern::undefined())
49        }
50    }
51}
52
53impl<Q: QueryContext> PatternName for Before<Q> {
54    fn name(&self) -> &'static str {
55        "BEFORE"
56    }
57}
58
59impl<Q: QueryContext> Matcher<Q> for Before<Q> {
60    fn execute<'a>(
61        &'a self,
62        binding: &Q::ResolvedPattern<'a>,
63        init_state: &mut State<'a, Q>,
64        context: &'a Q::ExecContext<'a>,
65        logs: &mut AnalysisLogs,
66    ) -> GritResult<bool> {
67        let Some(binding) = binding.get_last_binding() else {
68            return Ok(true);
69        };
70        let mut cur_state = init_state.clone();
71        // todo implement for empty and empty list
72        let Some(node) = binding.as_node() else {
73            return Ok(true);
74        };
75        let Some(next_node) = node.next_named_node() else {
76            return Ok(false);
77        };
78        if !self.before.execute(
79            &ResolvedPattern::from_node_binding(next_node),
80            &mut cur_state,
81            context,
82            logs,
83        )? {
84            return Ok(false);
85        }
86        *init_state = cur_state;
87        Ok(true)
88    }
89}