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