1use std::io::Error as IOError;
4
5use thiserror::Error;
6
7use crate::ast::*;
8use crate::syntax::pest::error::Error as PestError;
9use crate::syntax::pest::Span;
10use crate::syntax::Rule;
11
12#[derive(Clone, Debug, Eq, Error, PartialEq)]
18pub enum CardinalityError {
19 #[error("missing {name} clause")]
20 MissingClause { name: String },
21 #[error("duplicate {name} clauses")]
22 DuplicateClauses { name: String },
23 #[error("invalid single {name} clause")]
24 SingleClause { name: String },
25}
26
27impl CardinalityError {
28 pub fn missing<S: Into<String>>(name: S) -> Self {
29 CardinalityError::MissingClause { name: name.into() }
30 }
31
32 pub fn duplicate<S: Into<String>>(name: S) -> Self {
33 CardinalityError::DuplicateClauses { name: name.into() }
34 }
35
36 pub fn single<S: Into<String>>(name: S) -> Self {
37 CardinalityError::SingleClause { name: name.into() }
38 }
39}
40
41#[derive(Debug, Eq, Error, PartialEq)]
43pub enum SyntaxError {
44 #[error("unexpected rule: {actual:?} (expected {expected:?})")]
66 UnexpectedRule { expected: Rule, actual: Rule },
67
68 #[error("parser error: {error}")]
83 ParserError {
84 #[from]
85 error: Box<PestError<Rule>>,
86 },
87}
88
89impl SyntaxError {
90 pub(crate) fn with_offsets(self, line_offset: usize, offset: usize) -> Self {
92 use self::SyntaxError::*;
93 use crate::syntax::pest::error::InputLocation;
94 use crate::syntax::pest::error::LineColLocation;
95 match self {
96 e @ UnexpectedRule { .. } => e,
97 ParserError { mut error } => {
98 error.location = match error.location {
99 InputLocation::Pos(s) => InputLocation::Pos(s + offset),
100 InputLocation::Span((s, e)) => InputLocation::Span((s + offset, e + offset)),
101 };
102 error.line_col = match error.line_col {
103 LineColLocation::Pos((l, c)) => LineColLocation::Pos((l + line_offset, c)),
104 LineColLocation::Span((ls, cs), (le, ce)) => {
105 LineColLocation::Span((ls + line_offset, cs), (le + line_offset, ce))
106 }
107 };
108 ParserError { error }
109 }
110 }
111 }
112
113 pub(crate) fn with_path(self, path: &str) -> Self {
115 use self::SyntaxError::*;
116 match self {
117 e @ UnexpectedRule { .. } => e,
118 ParserError { error } => ParserError {
119 error: Box::new(error.with_path(path)),
120 },
121 }
122 }
123
124 pub(crate) fn with_span(self, span: Span) -> Self {
126 use self::SyntaxError::*;
127 match self {
128 e @ UnexpectedRule { .. } => e,
129 ParserError { error } => {
130 ParserError {
135 error: Box::new(PestError::new_from_span(error.variant, span)),
136 }
137 }
138 }
139 }
140}
141
142impl From<PestError<Rule>> for SyntaxError {
143 fn from(error: PestError<Rule>) -> Self {
144 Self::from(Box::new(error))
145 }
146}
147
148#[cfg(feature = "threading")]
150#[cfg_attr(feature = "_doc", doc(cfg(feature = "threading")))]
151#[derive(Debug, Eq, Error, PartialEq)]
152pub enum ThreadingError {
153 #[error("disconnected channel")]
155 DisconnectedChannel,
156}
157
158pub type Result<T> = std::result::Result<T, Error>;
160
161#[derive(Debug, Error)]
163pub enum Error {
164 #[error("syntax error: {error}")]
166 SyntaxError {
167 #[from]
168 error: SyntaxError,
169 },
170
171 #[error("IO error: {error}")]
184 IOError {
185 #[from]
186 error: IOError,
187 },
188
189 #[error("cardinality error: {inner}")]
191 CardinalityError {
192 id: Option<Ident>,
193 #[source]
194 inner: CardinalityError,
195 },
196
197 #[cfg(feature = "threading")]
199 #[cfg_attr(feature = "_doc", doc(cfg(feature = "threading")))]
200 #[error("threading error: {error}")]
201 ThreadingError {
202 #[from]
203 error: ThreadingError,
204 },
205}