nginx_discovery/parser/
token.rs1use crate::ast::Span;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Token {
8 pub kind: TokenKind,
10 pub span: Span,
12}
13
14impl Token {
15 #[must_use]
17 pub fn new(kind: TokenKind, span: Span) -> Self {
18 Self { kind, span }
19 }
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum TokenKind {
25 Word(String),
27
28 String(String),
30
31 Number(String),
33
34 Variable(String),
36
37 LeftBrace,
39
40 RightBrace,
42
43 Semicolon,
45
46 Comment(String),
48
49 Eof,
51}
52
53impl TokenKind {
54 #[must_use]
56 pub fn is_word(&self) -> bool {
57 matches!(self, Self::Word(_))
58 }
59
60 #[must_use]
62 pub fn is_string(&self) -> bool {
63 matches!(self, Self::String(_))
64 }
65
66 #[must_use]
68 pub fn is_number(&self) -> bool {
69 matches!(self, Self::Number(_))
70 }
71
72 #[must_use]
74 pub fn is_variable(&self) -> bool {
75 matches!(self, Self::Variable(_))
76 }
77
78 #[must_use]
80 pub fn as_string(&self) -> Option<&str> {
81 match self {
82 Self::Word(s) | Self::String(s) | Self::Variable(s) | Self::Number(s) => Some(s),
83 _ => None,
84 }
85 }
86}
87
88impl std::fmt::Display for TokenKind {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 match self {
91 Self::Word(s) => write!(f, "word '{s}'"),
92 Self::String(s) => write!(f, "string \"{s}\""),
93 Self::Number(s) => write!(f, "number '{s}'"),
94 Self::Variable(s) => write!(f, "variable '${s}'"),
95 Self::LeftBrace => write!(f, "'{{'"), Self::RightBrace => write!(f, "'}}'"), Self::Semicolon => write!(f, "';'"),
98 Self::Comment(s) => write!(f, "comment '# {s}'"),
99 Self::Eof => write!(f, "end of file"),
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn test_token_creation() {
110 let token = Token::new(TokenKind::Word("server".to_string()), Span::new(0, 6, 1, 1));
111 assert_eq!(token.kind, TokenKind::Word("server".to_string()));
112 }
113
114 #[test]
115 fn test_token_kind_checks() {
116 assert!(TokenKind::Word("test".to_string()).is_word());
117 assert!(TokenKind::String("test".to_string()).is_string());
118 assert!(TokenKind::Number("80".to_string()).is_number());
119 assert!(TokenKind::Variable("host".to_string()).is_variable());
120
121 assert!(!TokenKind::LeftBrace.is_word());
122 assert!(!TokenKind::Semicolon.is_string());
123 }
124
125 #[test]
126 fn test_as_string() {
127 assert_eq!(
128 TokenKind::Word("test".to_string()).as_string(),
129 Some("test")
130 );
131 assert_eq!(
132 TokenKind::String("value".to_string()).as_string(),
133 Some("value")
134 );
135 assert_eq!(TokenKind::LeftBrace.as_string(), None);
136 }
137
138 #[test]
139 fn test_token_display() {
140 assert_eq!(
141 TokenKind::Word("server".to_string()).to_string(),
142 "word 'server'"
143 );
144 assert_eq!(TokenKind::LeftBrace.to_string(), "'{'");
145 assert_eq!(TokenKind::Semicolon.to_string(), "';'");
146 }
147}