parol_runtime/lexer/
scanner_config.rs

1use crate::{ScannerIndex, TerminalIndex, Tokenizer};
2
3/// Scanner configuration fed into a TokenStream
4
5#[derive(Debug)]
6pub struct ScannerConfig {
7    /// Name of the scanner configuration, i.e. the scanner state or mode
8    pub name: &'static str,
9    /// The customized tokenizer for this scanner configuration
10    pub tokenizer: Tokenizer,
11    /// The mapping of token types to new scanner configurations
12    /// The entries are tuples of the terminal index and the new scanner configuration index and are
13    /// sorted by terminal index.
14    pub transitions: &'static [(TerminalIndex, ScannerIndex)],
15}
16
17impl ScannerConfig {
18    /// Create a new scanner configuration
19    pub fn new(
20        name: &'static str,
21        tokenizer: Tokenizer,
22        transitions: &'static [(TerminalIndex, ScannerIndex)],
23    ) -> Self {
24        Self {
25            name,
26            tokenizer,
27            transitions,
28        }
29    }
30
31    /// Check if the scanner configuration has a transition on the given terminal index
32    pub fn has_transition(&self, terminal_index: TerminalIndex) -> Option<ScannerIndex> {
33        self.transitions
34            .iter()
35            .find(|(term, _)| *term == terminal_index)
36            .map(|(_, scanner)| *scanner)
37    }
38}
39
40impl From<&ScannerConfig> for scnr::ScannerMode {
41    fn from(config: &ScannerConfig) -> Self {
42        scnr::ScannerMode::new(
43            config.name,
44            config.tokenizer.patterns.iter().map(|p| {
45                let sp = scnr::Pattern::new(p.regex.clone(), p.terminal as usize);
46                if let Some(lookahead) = p.lookahead.as_ref() {
47                    sp.with_lookahead(scnr::Lookahead {
48                        is_positive: lookahead.is_positive,
49                        pattern: lookahead.pattern.clone(),
50                    })
51                } else {
52                    sp
53                }
54            }),
55            config.transitions.iter().map(|(t, m)| (*t as usize, *m)),
56        )
57    }
58}