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