1use std::ops::Range;
4
5use crate::recognizer::Recognizer;
6use crate::token::{TokenId, TokenSourceError, TokenView};
7use thiserror::Error;
8
9#[derive(Debug, Error, Clone, Eq, PartialEq)]
10pub enum AntlrError {
11 #[error("mismatched input: expected {expected}, found {found}")]
12 MismatchedInput { expected: String, found: String },
13 #[error("no viable alternative at input {input}")]
14 NoViableAlternative { input: String },
15 #[error("lexer error at {line}:{column}: {message}")]
16 LexerError {
17 line: usize,
18 column: usize,
19 message: String,
20 },
21 #[error("parser error at {line}:{column}: {message}")]
22 ParserError {
23 line: usize,
24 column: usize,
25 message: String,
26 offending: Option<TokenId>,
32 },
33 #[error("unsupported runtime feature: {0}")]
34 Unsupported(String),
35}
36
37#[derive(Clone, Debug, Eq, PartialEq)]
39#[non_exhaustive]
40pub struct SyntaxErrorEvent<'a> {
41 pub offending: Option<TokenView<'a>>,
46 pub line: usize,
48 pub column: usize,
50 pub span: Option<Range<usize>>,
55 pub message: &'a str,
57 pub error: Option<&'a AntlrError>,
59}
60
61impl<'a> From<&'a TokenSourceError> for SyntaxErrorEvent<'a> {
62 fn from(error: &'a TokenSourceError) -> Self {
63 Self {
64 offending: None,
65 line: error.line,
66 column: error.column,
67 span: error.span.clone(),
68 message: &error.message,
69 error: None,
70 }
71 }
72}
73
74pub trait ErrorListener<R: Recognizer + ?Sized> {
81 fn syntax_error(&mut self, recognizer: &R, event: &SyntaxErrorEvent<'_>);
83}
84
85#[derive(Debug, Default)]
86pub struct ConsoleErrorListener;
87
88impl<R: Recognizer + ?Sized> ErrorListener<R> for ConsoleErrorListener {
89 #[allow(clippy::print_stderr)]
90 fn syntax_error(&mut self, _recognizer: &R, event: &SyntaxErrorEvent<'_>) {
91 eprintln!("line {}:{} {}", event.line, event.column, event.message);
92 }
93}