1use alloc::boxed::Box;
2use alloc::string::String;
3use core::fmt;
4use regex_automata::meta::BuildError as RaBuildError;
5
6pub type Result<T> = ::core::result::Result<T, Error>;
8
9pub type ParseErrorPosition = usize;
10
11#[derive(Clone, Debug)]
13#[non_exhaustive]
14pub enum Error {
15 ParseError(ParseErrorPosition, ParseError),
17 CompileError(Box<CompileError>),
19 RuntimeError(RuntimeError),
21}
22
23#[derive(Clone, Debug)]
25#[non_exhaustive]
26pub enum ParseError {
27 GeneralParseError(String),
29 UnclosedOpenParen,
31 InvalidRepeat,
33 RecursionExceeded,
35 TrailingBackslash,
37 InvalidEscape(String),
39 UnclosedUnicodeName,
41 InvalidHex,
43 InvalidCodepointValue,
45 InvalidClass,
47 UnknownFlag(String),
49 ChangingUnicodeModeUnsupported,
51 InvalidBackref,
53 TargetNotRepeatable,
55 InvalidGroupName,
57 InvalidGroupNameBackref(String),
59}
60
61#[derive(Clone, Debug)]
63#[non_exhaustive]
64pub enum CompileError {
65 InnerError(RaBuildError),
67 LookBehindNotConst,
69 VariableLookBehindRequiresFeature,
71 DfaBuildError(String, String),
73 InvalidGroupName,
75 InvalidGroupNameBackref(String),
77 InvalidBackref(usize),
79 NamedBackrefOnly,
81 FeatureNotYetSupported(String),
83 SubroutineCallTargetNotFound(String, usize),
85 LeftRecursiveSubroutineCall(String),
87 NeverEndingRecursion,
89 PatternTooComplex,
94 UnexpectedGeneralError(String),
96 PatternCanNeverMatch,
100 UnresolvedAstNode(usize, String),
102}
103
104#[derive(Clone, Debug)]
106#[non_exhaustive]
107pub enum RuntimeError {
108 StackOverflow,
110 BacktrackLimitExceeded,
114}
115
116#[cfg(feature = "std")]
117impl ::std::error::Error for Error {}
118
119impl fmt::Display for ParseError {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 match self {
122 ParseError::GeneralParseError(s) => write!(f, "General parsing error: {}", s),
123 ParseError::UnclosedOpenParen => {
124 write!(f, "Opening parenthesis without closing parenthesis")
125 }
126 ParseError::InvalidRepeat => write!(f, "Invalid repeat syntax"),
127 ParseError::RecursionExceeded => write!(f, "Pattern too deeply nested"),
128 ParseError::TrailingBackslash => write!(f, "Backslash without following character"),
129 ParseError::InvalidEscape(s) => write!(f, "Invalid escape: {}", s),
130 ParseError::UnclosedUnicodeName => write!(f, "Unicode escape not closed"),
131 ParseError::InvalidHex => write!(f, "Invalid hex escape"),
132 ParseError::InvalidCodepointValue => {
133 write!(f, "Invalid codepoint for hex or unicode escape")
134 }
135 ParseError::InvalidClass => write!(f, "Invalid character class"),
136 ParseError::UnknownFlag(s) => write!(f, "Unknown group flag: {}", s),
137 ParseError::ChangingUnicodeModeUnsupported => {
138 write!(f, "Changing Unicode mode inline is not supported")
139 }
140 ParseError::InvalidBackref => write!(f, "Invalid back reference"),
141 ParseError::InvalidGroupName => write!(f, "Could not parse group name"),
142 ParseError::InvalidGroupNameBackref(s) => {
143 write!(f, "Invalid group name in back reference: {}", s)
144 }
145 ParseError::TargetNotRepeatable => write!(f, "Target of repeat operator is invalid"),
146 }
147 }
148}
149
150impl fmt::Display for CompileError {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 match self {
153 CompileError::InnerError(e) => write!(f, "Regex error: {}", e),
154 CompileError::LookBehindNotConst => {
155 write!(f, "Look-behind assertion without constant size")
156 },
157 CompileError::VariableLookBehindRequiresFeature => {
158 write!(f, "Variable-length lookbehind requires the 'variable-lookbehinds' feature")
159 },
160 CompileError::DfaBuildError(pattern, e) => {
161 write!(f, "Failed to build DFA for {}: {}", pattern, e)
162 },
163 CompileError::InvalidGroupName => write!(f, "Could not parse group name"),
164 CompileError::InvalidGroupNameBackref(s) => write!(f, "Invalid group name in back reference: {}", s),
165 CompileError::InvalidBackref(g) => write!(f, "Invalid back reference to group {}", g),
166 CompileError::NamedBackrefOnly => write!(f, "Numbered backref/call not allowed because named group was used, use a named backref instead"),
167 CompileError::FeatureNotYetSupported(s) => write!(f, "Regex uses currently unimplemented feature: {}", s),
168 CompileError::SubroutineCallTargetNotFound(s, ix) => {
169 write!(f, "Subroutine call target not found at position {}: {}", ix, s)
170 }
171 CompileError::LeftRecursiveSubroutineCall(s) => {
172 write!(f, "Left-recursive subroutine call detected: {}", s)
173 }
174 CompileError::NeverEndingRecursion => {
175 write!(f, "Never-ending recursive subroutine call detected")
176 }
177 CompileError::PatternTooComplex => {
178 write!(
179 f,
180 "Pattern is too complex: it exceeded the configured maximum number of VM \
181 instructions. Try increasing the `max_prog_size` limit or simplifying the \
182 pattern."
183 )
184 }
185 CompileError::UnexpectedGeneralError(s) => {
186 write!(f, "Unexpected general compilation error: {}", s)
187 }
188 CompileError::PatternCanNeverMatch => {
189 write!(f, "Pattern can never match: the regex is zero-width only but find_not_empty is set")
190 }
191 CompileError::UnresolvedAstNode(ix, node) => {
192 write!(f, "Unresolved AST node encountered during analysis at position {}: {}", ix, node)
193 }
194 }
195 }
196}
197
198impl fmt::Display for RuntimeError {
199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200 match self {
201 RuntimeError::StackOverflow => write!(f, "Max stack size exceeded for backtracking"),
202 RuntimeError::BacktrackLimitExceeded => {
203 write!(f, "Max limit for backtracking count exceeded")
204 }
205 }
206 }
207}
208
209impl fmt::Display for Error {
210 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
211 match self {
212 Error::ParseError(position, parse_error) => {
213 write!(f, "Parsing error at position {}: {}", position, parse_error)
214 }
215 Error::CompileError(compile_error) => {
216 write!(f, "Error compiling regex: {}", compile_error)
217 }
218 Error::RuntimeError(runtime_error) => {
219 write!(f, "Error executing regex: {}", runtime_error)
220 }
221 }
222 }
223}
224
225impl From<CompileError> for Error {
226 fn from(compile_error: CompileError) -> Self {
227 Error::CompileError(Box::new(compile_error))
228 }
229}