Skip to main content

rawk_core/
parse_error.rs

1use crate::token::Token;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum ParseErrorKind {
5    ExpectedRule,
6    ExpectedStatement,
7    ExpectedIdentifier,
8    UnsupportedStatement,
9    UnsupportedSubTarget,
10    ExpectedLeftParen,
11    ExpectedLeftBrace,
12    ExpectedRightSquareBracket,
13    ExpectedComma,
14    ExpectedColon,
15    ExpectedSemicolon,
16    ExpectedWhile,
17    ExpectedRightBrace,
18    ExpectedRightParen,
19    MissingPrintfFormatString,
20    InvalidNumericLiteral,
21}
22
23#[derive(Debug, Clone, PartialEq)]
24pub struct ParseError<'a> {
25    pub kind: ParseErrorKind,
26    pub token: Token<'a>,
27}
28
29impl std::fmt::Display for ParseError<'_> {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        match &self.kind {
32            ParseErrorKind::ExpectedRule => write!(
33                f,
34                "unexpected token {:?} ({:?}) at byte {}: expected rule",
35                self.token.kind, self.token.literal, self.token.span.start
36            ),
37            ParseErrorKind::ExpectedStatement => write!(
38                f,
39                "unexpected token {:?} ({:?}) at byte {}: expected statement",
40                self.token.kind, self.token.literal, self.token.span.start
41            ),
42            ParseErrorKind::ExpectedIdentifier => write!(
43                f,
44                "unexpected token {:?} ({:?}) at byte {}: expected identifier",
45                self.token.kind, self.token.literal, self.token.span.start
46            ),
47            ParseErrorKind::UnsupportedStatement => write!(
48                f,
49                "unexpected token {:?} ({:?}) at byte {}: unsupported statement syntax",
50                self.token.kind, self.token.literal, self.token.span.start
51            ),
52            ParseErrorKind::UnsupportedSubTarget => write!(
53                f,
54                "unexpected token {:?} ({:?}) at byte {}: sub target argument is not supported",
55                self.token.kind, self.token.literal, self.token.span.start
56            ),
57            ParseErrorKind::ExpectedLeftParen => write!(
58                f,
59                "unexpected token {:?} ({:?}) at byte {}: expected left paren",
60                self.token.kind, self.token.literal, self.token.span.start
61            ),
62            ParseErrorKind::ExpectedLeftBrace => write!(
63                f,
64                "unexpected token {:?} ({:?}) at byte {}: expected left brace",
65                self.token.kind, self.token.literal, self.token.span.start
66            ),
67            ParseErrorKind::ExpectedRightSquareBracket => write!(
68                f,
69                "unexpected token {:?} ({:?}) at byte {}: expected right square bracket",
70                self.token.kind, self.token.literal, self.token.span.start
71            ),
72            ParseErrorKind::ExpectedComma => write!(
73                f,
74                "unexpected token {:?} ({:?}) at byte {}: expected comma",
75                self.token.kind, self.token.literal, self.token.span.start
76            ),
77            ParseErrorKind::ExpectedColon => write!(
78                f,
79                "unexpected token {:?} ({:?}) at byte {}: expected colon",
80                self.token.kind, self.token.literal, self.token.span.start
81            ),
82            ParseErrorKind::ExpectedSemicolon => write!(
83                f,
84                "unexpected token {:?} ({:?}) at byte {}: expected semicolon",
85                self.token.kind, self.token.literal, self.token.span.start
86            ),
87            ParseErrorKind::ExpectedWhile => write!(
88                f,
89                "unexpected token {:?} ({:?}) at byte {}: expected while",
90                self.token.kind, self.token.literal, self.token.span.start
91            ),
92            ParseErrorKind::ExpectedRightBrace => write!(
93                f,
94                "unexpected token {:?} ({:?}) at byte {}: expected right brace",
95                self.token.kind, self.token.literal, self.token.span.start
96            ),
97            ParseErrorKind::ExpectedRightParen => write!(
98                f,
99                "unexpected token {:?} ({:?}) at byte {}: expected right paren",
100                self.token.kind, self.token.literal, self.token.span.start
101            ),
102            ParseErrorKind::MissingPrintfFormatString => write!(
103                f,
104                "printf requires a format string at byte {}",
105                self.token.span.start
106            ),
107            ParseErrorKind::InvalidNumericLiteral => write!(
108                f,
109                "invalid numeric literal {:?} at byte {}",
110                self.token.literal, self.token.span.start
111            ),
112        }
113    }
114}
115
116impl std::error::Error for ParseError<'_> {}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use crate::token::{Token, TokenKind};
122
123    fn parse_error(kind: ParseErrorKind, token: Token<'static>) -> ParseError<'static> {
124        ParseError { kind, token }
125    }
126
127    #[test]
128    fn display_expected_rule_error() {
129        let err = parse_error(
130            ParseErrorKind::ExpectedRule,
131            Token::new(TokenKind::Else, "else", 12),
132        );
133
134        assert_eq!(
135            format!("{err}"),
136            "unexpected token Else (\"else\") at byte 12: expected rule"
137        );
138    }
139
140    #[test]
141    fn display_expected_statement_error() {
142        let err = parse_error(
143            ParseErrorKind::ExpectedStatement,
144            Token::new(TokenKind::Else, "else", 4),
145        );
146
147        assert_eq!(
148            format!("{err}"),
149            "unexpected token Else (\"else\") at byte 4: expected statement"
150        );
151    }
152
153    #[test]
154    fn display_expected_identifier_error() {
155        let err = parse_error(
156            ParseErrorKind::ExpectedIdentifier,
157            Token::new(TokenKind::Number, "1", 8),
158        );
159
160        assert_eq!(
161            format!("{err}"),
162            "unexpected token Number (\"1\") at byte 8: expected identifier"
163        );
164    }
165
166    #[test]
167    fn display_unsupported_statement_error() {
168        let err = parse_error(
169            ParseErrorKind::UnsupportedStatement,
170            Token::new(TokenKind::Plus, "+", 6),
171        );
172
173        assert_eq!(
174            format!("{err}"),
175            "unexpected token Plus (\"+\") at byte 6: unsupported statement syntax"
176        );
177    }
178
179    #[test]
180    fn display_unsupported_sub_target_error() {
181        let err = parse_error(
182            ParseErrorKind::UnsupportedSubTarget,
183            Token::new(TokenKind::Comma, ",", 12),
184        );
185
186        assert_eq!(
187            format!("{err}"),
188            "unexpected token Comma (\",\") at byte 12: sub target argument is not supported"
189        );
190    }
191
192    #[test]
193    fn display_expected_left_paren_error() {
194        let err = parse_error(
195            ParseErrorKind::ExpectedLeftParen,
196            Token::new(TokenKind::Identifier, "x", 5),
197        );
198
199        assert_eq!(
200            format!("{err}"),
201            "unexpected token Identifier (\"x\") at byte 5: expected left paren"
202        );
203    }
204
205    #[test]
206    fn display_expected_left_brace_error() {
207        let err = parse_error(
208            ParseErrorKind::ExpectedLeftBrace,
209            Token::new(TokenKind::Print, "print", 6),
210        );
211
212        assert_eq!(
213            format!("{err}"),
214            "unexpected token Print (\"print\") at byte 6: expected left brace"
215        );
216    }
217
218    #[test]
219    fn display_expected_right_square_bracket_error() {
220        let err = parse_error(
221            ParseErrorKind::ExpectedRightSquareBracket,
222            Token::new(TokenKind::Assign, "=", 9),
223        );
224
225        assert_eq!(
226            format!("{err}"),
227            "unexpected token Assign (\"=\") at byte 9: expected right square bracket"
228        );
229    }
230
231    #[test]
232    fn display_expected_comma_error() {
233        let err = parse_error(
234            ParseErrorKind::ExpectedComma,
235            Token::new(TokenKind::Identifier, "arr", 11),
236        );
237
238        assert_eq!(
239            format!("{err}"),
240            "unexpected token Identifier (\"arr\") at byte 11: expected comma"
241        );
242    }
243
244    #[test]
245    fn display_expected_colon_error() {
246        let err = parse_error(
247            ParseErrorKind::ExpectedColon,
248            Token::new(TokenKind::RightCurlyBrace, "}", 13),
249        );
250
251        assert_eq!(
252            format!("{err}"),
253            "unexpected token RightCurlyBrace (\"}\") at byte 13: expected colon"
254        );
255    }
256
257    #[test]
258    fn display_expected_semicolon_error() {
259        let err = parse_error(
260            ParseErrorKind::ExpectedSemicolon,
261            Token::new(TokenKind::Identifier, "i", 15),
262        );
263
264        assert_eq!(
265            format!("{err}"),
266            "unexpected token Identifier (\"i\") at byte 15: expected semicolon"
267        );
268    }
269
270    #[test]
271    fn display_expected_while_error() {
272        let err = parse_error(
273            ParseErrorKind::ExpectedWhile,
274            Token::new(TokenKind::RightCurlyBrace, "}", 7),
275        );
276
277        assert_eq!(
278            format!("{err}"),
279            "unexpected token RightCurlyBrace (\"}\") at byte 7: expected while"
280        );
281    }
282
283    #[test]
284    fn display_expected_right_paren_error() {
285        let err = parse_error(
286            ParseErrorKind::ExpectedRightParen,
287            Token::new(TokenKind::Print, "print", 10),
288        );
289
290        assert_eq!(
291            format!("{err}"),
292            "unexpected token Print (\"print\") at byte 10: expected right paren"
293        );
294    }
295
296    #[test]
297    fn display_expected_right_brace_error() {
298        let err = parse_error(
299            ParseErrorKind::ExpectedRightBrace,
300            Token::new(TokenKind::Eof, "", 16),
301        );
302
303        assert_eq!(
304            format!("{err}"),
305            "unexpected token Eof (\"\") at byte 16: expected right brace"
306        );
307    }
308
309    #[test]
310    fn display_missing_printf_format_string_error() {
311        let err = parse_error(
312            ParseErrorKind::MissingPrintfFormatString,
313            Token::new(TokenKind::RightCurlyBrace, "}", 14),
314        );
315
316        assert_eq!(
317            format!("{err}"),
318            "printf requires a format string at byte 14"
319        );
320    }
321
322    #[test]
323    fn display_invalid_numeric_literal_error() {
324        let err = parse_error(
325            ParseErrorKind::InvalidNumericLiteral,
326            Token::new(TokenKind::Number, "0xZZ", 3),
327        );
328
329        assert_eq!(
330            format!("{err}"),
331            "invalid numeric literal \"0xZZ\" at byte 3"
332        );
333    }
334}