1use crate::span::Span;
2use std::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum ParseErrorKind {
7 UnexpectedEof,
9 UnclosedDelimiter,
11 InvalidSyntax,
13 UnknownDirective,
15 InvalidMetadata,
17 Other,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct ParseError {
24 pub message: String,
26 pub span: Option<Span>,
28 pub kind: ParseErrorKind,
30 pub recoverable: bool,
32}
33
34impl ParseError {
35 pub fn new(message: impl Into<String>, span: Option<Span>) -> Self {
37 Self {
38 message: message.into(),
39 span,
40 kind: ParseErrorKind::Other,
41 recoverable: true,
42 }
43 }
44
45 pub fn unexpected_eof(span: Option<Span>) -> Self {
47 Self {
48 message: "unexpected end of input".to_string(),
49 span,
50 kind: ParseErrorKind::UnexpectedEof,
51 recoverable: false,
52 }
53 }
54
55 pub fn unclosed_delimiter(delimiter: &str, span: Option<Span>) -> Self {
57 Self {
58 message: format!("unclosed {}", delimiter),
59 span,
60 kind: ParseErrorKind::UnclosedDelimiter,
61 recoverable: true,
62 }
63 }
64
65 pub fn invalid_syntax(context: &str, span: Option<Span>) -> Self {
67 Self {
68 message: format!("invalid syntax in {}", context),
69 span,
70 kind: ParseErrorKind::InvalidSyntax,
71 recoverable: true,
72 }
73 }
74
75 pub fn unknown_directive(directive: &str, span: Option<Span>) -> Self {
77 Self {
78 message: format!("unknown directive: {}", directive),
79 span,
80 kind: ParseErrorKind::UnknownDirective,
81 recoverable: true,
82 }
83 }
84
85 pub fn with_kind(mut self, kind: ParseErrorKind) -> Self {
87 self.kind = kind;
88 self
89 }
90
91 pub fn non_recoverable(mut self) -> Self {
93 self.recoverable = false;
94 self
95 }
96}
97
98impl fmt::Display for ParseError {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 write!(f, "{}", self.message)?;
101 if let Some(span) = self.span {
102 write!(f, " at bytes {}..{}", span.start, span.end)?;
103 }
104 Ok(())
105 }
106}
107
108impl std::error::Error for ParseError {}
109
110#[derive(Debug, Clone, Default)]
112pub struct ParseErrors {
113 errors: Vec<ParseError>,
114}
115
116impl ParseErrors {
117 pub fn new() -> Self {
119 Self { errors: Vec::new() }
120 }
121
122 pub fn push(&mut self, error: ParseError) {
124 self.errors.push(error);
125 }
126
127 pub fn is_empty(&self) -> bool {
129 self.errors.is_empty()
130 }
131
132 pub fn len(&self) -> usize {
134 self.errors.len()
135 }
136
137 pub fn iter(&self) -> impl Iterator<Item = &ParseError> {
139 self.errors.iter()
140 }
141
142 pub fn has_fatal(&self) -> bool {
144 self.errors.iter().any(|e| !e.recoverable)
145 }
146}
147
148impl IntoIterator for ParseErrors {
149 type Item = ParseError;
150 type IntoIter = std::vec::IntoIter<ParseError>;
151
152 fn into_iter(self) -> Self::IntoIter {
153 self.errors.into_iter()
154 }
155}