wagon_parser/parser/
terminal.rs

1
2use derivative::Derivative;
3use std::{fmt::Display, write};
4
5use regex_automata::dfa::dense::DFA;
6
7use super::{Parse, LexerBridge, ParseResult, Tokens, WagParseError, Spannable, ResultNext};
8use wagon_lexer::productions::Productions;
9use wagon_macros::match_error;
10
11
12#[derive(Debug, Clone, Derivative)]
13#[derivative(PartialEq, Hash)]
14/// A terminal for the grammar.
15///
16/// # Grammar
17/// <code>[Terminal] -> Regex | String;</code>
18pub enum Terminal {
19    /// A terminal described as a regex. 
20	Regex(
21        /// The pattern
22        String, 
23        #[derivative(PartialEq="ignore")]
24        #[derivative(Hash="ignore")]
25        /// A fully valid [`DFA`] which can either be used correctly, or serialized as needed.
26        Box<DFA<Vec<u32>>> // DFA is on the heap because it is very big.
27    ), 
28    /// A string to exactly match.
29	LitString(String)
30}
31
32impl Parse for Terminal {
33    fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> where Self: Sized {
34        match_error!(match lexer.next_result()? {
35        	Tokens::ProductionToken(Productions::LitString(x)) => Ok(Self::LitString(x)),
36        	Tokens::ProductionToken(Productions::LitRegex(x)) => {
37                match DFA::new(&x) {
38                    Ok(dfa) => Ok(Self::Regex(x, Box::new(dfa))),
39                    Err(e) => Err(WagParseError::RegexError(Box::new(e), lexer.span(), x))
40                }
41            },
42        })
43    }
44}
45
46impl Display for Terminal {
47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        match self {
49            Self::Regex(r, _) => write!(f, "/{r}/"),
50            Self::LitString(s) => write!(f, "'{s}'"),
51        }
52    }
53}
54
55impl Eq for Terminal {}