1use crate::coords::Coords;
6use crate::lexer::lexer_core::Token;
7use std::fmt::{Display, Formatter};
8use std::io::BufRead;
9
10pub type ParserResult<T> = Result<T, ParserError>;
12
13#[derive(Debug, Copy, Clone)]
15pub enum ParserErrorSource {
16 LexerInput,
18 Lexer,
20 DomParser,
22 SaxParser,
24}
25
26impl Display for ParserErrorSource {
27 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28 match self {
29 ParserErrorSource::LexerInput => write!(f, "lexer input"),
30 ParserErrorSource::Lexer => write!(f, "lexing"),
31 ParserErrorSource::DomParser => write!(f, "DOM parsing"),
32 ParserErrorSource::SaxParser => write!(f, "SAX parsing"),
33 }
34 }
35}
36
37#[derive(Debug, Clone, PartialEq)]
39pub enum ParserErrorDetails {
40 InvalidFile,
42 ZeroLengthInput,
44 EndOfInput,
46 StreamFailure,
49 NonUtf8InputDetected,
51 UnexpectedToken(Token),
54 PairExpected,
56 InvalidRootObject,
58 InvalidObject,
60 InvalidArray,
62 InvalidCharacter(char),
64 MatchFailed(String, String),
66 InvalidNumericRepresentation(String),
68 InvalidEscapeSequence(String),
70 InvalidUnicodeEscapeSequence(String),
72}
73
74impl Display for ParserErrorDetails {
75 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
76 match self {
77 ParserErrorDetails::InvalidFile => write!(f, "invalid file specified"),
78 ParserErrorDetails::ZeroLengthInput => write!(f, "zero length input"),
79 ParserErrorDetails::EndOfInput => write!(f, "end of input reached"),
80 ParserErrorDetails::StreamFailure => write!(f, "failure in the underlying stream"),
81 ParserErrorDetails::NonUtf8InputDetected => write!(f, "non-UTF8 input"),
82 ParserErrorDetails::UnexpectedToken(token) => {
83 write!(f, "unexpected token found: {}", token)
84 }
85 ParserErrorDetails::PairExpected => {
86 write!(f, "pair expected, something else was found")
87 }
88 ParserErrorDetails::InvalidRootObject => write!(f, "invalid JSON"),
89 ParserErrorDetails::InvalidObject => write!(f, "invalid object"),
90 ParserErrorDetails::InvalidArray => write!(f, "invalid array"),
91 ParserErrorDetails::InvalidCharacter(ch) => write!(f, "invalid character: \'{}\'", ch),
92 ParserErrorDetails::MatchFailed(first, second) => write!(
93 f,
94 "a match failed. Looking for \"{}\", found \"{}\"",
95 first, second
96 ),
97 ParserErrorDetails::InvalidNumericRepresentation(repr) => {
98 write!(f, "invalid number representation: \"{}\"", repr)
99 }
100 ParserErrorDetails::InvalidEscapeSequence(seq) => {
101 write!(f, "invalid escape sequence: \"{}\"", seq)
102 }
103 ParserErrorDetails::InvalidUnicodeEscapeSequence(seq) => {
104 write!(f, "invalid unicode escape sequence: \"{}\"", seq)
105 }
106 }
107 }
108}
109
110#[derive(Debug, Clone)]
112pub struct ParserError {
113 pub source: ParserErrorSource,
115 pub details: ParserErrorDetails,
117 pub coords: Option<Coords>,
119}
120
121impl Display for ParserError {
122 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
123 if self.coords.is_some() {
124 write!(
125 f,
126 "Source: {}, Details: {}, Coords: {}",
127 self.source,
128 self.details,
129 self.coords.unwrap()
130 )
131 } else {
132 write!(f, "Source: {}, Details: {}", self.source, self.details)
133 }
134 }
135}
136#[macro_export]
137macro_rules! lexer_input_error {
138 ($details: expr, $coords : expr) => {
139 Err(ParserError {
140 source: ParserErrorSource::LexerInput,
141 details: $details,
142 coords: Some($coords),
143 })
144 };
145 ($details: expr) => {
146 Err(ParserError {
147 source: ParserErrorSource::LexerInput,
148 details: $details,
149 coords: None,
150 })
151 };
152}
153#[macro_export]
155macro_rules! lexer_error {
156 ($details: expr, $coords : expr) => {
157 Err(ParserError {
158 source: ParserErrorSource::Lexer,
159 details: $details,
160 coords: Some($coords),
161 })
162 };
163 ($details: expr) => {
164 Err(ParserError {
165 source: ParserErrorSource::Lexer,
166 details: $details,
167 coords: None,
168 })
169 };
170}
171
172#[macro_export]
174macro_rules! dom_parser_error {
175 ($details: expr, $coords: expr) => {
176 Err(ParserError {
177 source: ParserErrorSource::DomParser,
178 details: $details,
179 coords: Some($coords),
180 })
181 };
182 ($details: expr) => {
183 Err(ParserError {
184 source: ParserErrorSource::DomParser,
185 details: $details,
186 coords: None,
187 })
188 };
189}
190
191#[macro_export]
193macro_rules! sax_parser_error {
194 ($details: expr, $coords: expr) => {
195 Err(ParserError {
196 source: ParserErrorSource::SaxParser,
197 details: $details,
198 coords: Some($coords),
199 })
200 };
201 ($details: expr) => {
202 Err(ParserError {
203 source: ParserErrorSource::SaxParser,
204 details: $details,
205 coords: None,
206 })
207 };
208}