1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::borrow::Borrow;
use std::fmt::Debug;
use std::sync::Arc;

use anyhow::Result;

pub use label_lookahead_matcher::LabelLookAheadMatcher;
pub(super) use label_lookahead_relabeler::LabelLookAheadRelabeler;
pub use tr_lookahead_matcher::TrLookAheadMatcher;
pub use trivial_lookahead_matcher::TrivialLookAheadMatcher;

use crate::algorithms::compose::matchers::MatcherFlags;
use crate::algorithms::compose::matchers::{MatchType, Matcher};
use crate::fst_traits::Fst;
use crate::semirings::Semiring;
use crate::{Label, StateId, Tr, NO_STATE_ID};

mod label_lookahead_matcher;
pub(super) mod label_lookahead_relabeler;
mod tr_lookahead_matcher;
mod trivial_lookahead_matcher;

pub trait MatcherFlagsTrait: Debug + Clone {
    fn flags() -> MatcherFlags;
}

#[derive(Clone, Debug)]
pub struct LookAheadMatcherData<W: Semiring> {
    pub lookahead_weight: W,
    pub prefix_tr: Tr<W>,
}

impl<W: Semiring> Default for LookAheadMatcherData<W> {
    fn default() -> Self {
        LookAheadMatcherData::new(W::one(), Tr::new(0, 0, W::one(), NO_STATE_ID))
    }
}

impl<W: Semiring> LookAheadMatcherData<W> {
    pub fn new(lookahead_weight: W, prefix_tr: Tr<W>) -> Self {
        Self {
            lookahead_weight,
            prefix_tr,
        }
    }

    pub fn clear_lookahead_weight(&mut self) {
        self.lookahead_weight = W::one();
    }
    pub fn set_lookahead_weight(&mut self, weight: W) {
        self.lookahead_weight = weight;
    }
    pub fn clear_lookahead_prefix(&mut self) {
        self.prefix_tr.nextstate = NO_STATE_ID;
    }
    pub fn set_lookahead_prefix(&mut self, tr: Tr<W>) {
        self.prefix_tr = tr;
    }
    pub fn default_lookahead_prefix(&self, tr: &mut Tr<W>) -> bool {
        if self.prefix_tr.nextstate != NO_STATE_ID {
            *tr = self.prefix_tr.clone();
            true
        } else {
            false
        }
    }
}

pub trait LookaheadMatcher<W: Semiring, F: Fst<W>, B: Borrow<F>>: Matcher<W, F, B> {
    type MatcherData: Clone;
    fn data(&self) -> Option<&Arc<Self::MatcherData>>;

    fn new_with_data(
        fst: B,
        match_type: MatchType,
        data: Option<Arc<Self::MatcherData>>,
    ) -> Result<Self>
    where
        Self: std::marker::Sized;

    fn create_data<F2: Fst<W>, BF2: Borrow<F2>>(
        fst: BF2,
        match_type: MatchType,
    ) -> Result<Option<Self::MatcherData>>;

    fn init_lookahead_fst<LF: Fst<W>, BLF: Borrow<LF> + Clone>(&mut self, lfst: &BLF)
        -> Result<()>;
    // Are there paths from a state in the lookahead FST that can be read from
    // the curent matcher state?

    fn lookahead_fst<LF: Fst<W>, BLF: Borrow<LF>>(
        &self,
        matcher_state: StateId,
        lfst: &BLF,
        lfst_state: StateId,
    ) -> Result<Option<LookAheadMatcherData<W>>>;

    // Can the label be read from the current matcher state after possibly
    // following epsilon transitions?
    fn lookahead_label(&self, state: StateId, label: Label) -> Result<bool>;
    fn lookahead_prefix(&self, tr: &mut Tr<W>, la_matcher_data: &LookAheadMatcherData<W>) -> bool;
}