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 UnexpectedGeneralError(String),
91 PatternCanNeverMatch,
95 UnresolvedAstNode(usize, String),
97}
98
99#[derive(Clone, Debug)]
101#[non_exhaustive]
102pub enum RuntimeError {
103 StackOverflow,
105 BacktrackLimitExceeded,
109}
110
111#[cfg(feature = "std")]
112impl ::std::error::Error for Error {}
113
114impl fmt::Display for ParseError {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 match self {
117 ParseError::GeneralParseError(s) => write!(f, "General parsing error: {}", s),
118 ParseError::UnclosedOpenParen => {
119 write!(f, "Opening parenthesis without closing parenthesis")
120 }
121 ParseError::InvalidRepeat => write!(f, "Invalid repeat syntax"),
122 ParseError::RecursionExceeded => write!(f, "Pattern too deeply nested"),
123 ParseError::TrailingBackslash => write!(f, "Backslash without following character"),
124 ParseError::InvalidEscape(s) => write!(f, "Invalid escape: {}", s),
125 ParseError::UnclosedUnicodeName => write!(f, "Unicode escape not closed"),
126 ParseError::InvalidHex => write!(f, "Invalid hex escape"),
127 ParseError::InvalidCodepointValue => {
128 write!(f, "Invalid codepoint for hex or unicode escape")
129 }
130 ParseError::InvalidClass => write!(f, "Invalid character class"),
131 ParseError::UnknownFlag(s) => write!(f, "Unknown group flag: {}", s),
132 ParseError::ChangingUnicodeModeUnsupported => {
133 write!(f, "Changing Unicode mode inline is not supported")
134 }
135 ParseError::InvalidBackref => write!(f, "Invalid back reference"),
136 ParseError::InvalidGroupName => write!(f, "Could not parse group name"),
137 ParseError::InvalidGroupNameBackref(s) => {
138 write!(f, "Invalid group name in back reference: {}", s)
139 }
140 ParseError::TargetNotRepeatable => write!(f, "Target of repeat operator is invalid"),
141 }
142 }
143}
144
145impl fmt::Display for CompileError {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 match self {
148 CompileError::InnerError(e) => write!(f, "Regex error: {}", e),
149 CompileError::LookBehindNotConst => {
150 write!(f, "Look-behind assertion without constant size")
151 },
152 CompileError::VariableLookBehindRequiresFeature => {
153 write!(f, "Variable-length lookbehind requires the 'variable-lookbehinds' feature")
154 },
155 CompileError::DfaBuildError(pattern, e) => {
156 write!(f, "Failed to build DFA for {}: {}", pattern, e)
157 },
158 CompileError::InvalidGroupName => write!(f, "Could not parse group name"),
159 CompileError::InvalidGroupNameBackref(s) => write!(f, "Invalid group name in back reference: {}", s),
160 CompileError::InvalidBackref(g) => write!(f, "Invalid back reference to group {}", g),
161 CompileError::NamedBackrefOnly => write!(f, "Numbered backref/call not allowed because named group was used, use a named backref instead"),
162 CompileError::FeatureNotYetSupported(s) => write!(f, "Regex uses currently unimplemented feature: {}", s),
163 CompileError::SubroutineCallTargetNotFound(s, ix) => {
164 write!(f, "Subroutine call target not found at position {}: {}", ix, s)
165 }
166 CompileError::LeftRecursiveSubroutineCall(s) => {
167 write!(f, "Left-recursive subroutine call detected: {}", s)
168 }
169 CompileError::NeverEndingRecursion => {
170 write!(f, "Never-ending recursive subroutine call detected")
171 }
172 CompileError::UnexpectedGeneralError(s) => {
173 write!(f, "Unexpected general compilation error: {}", s)
174 }
175 CompileError::PatternCanNeverMatch => {
176 write!(f, "Pattern can never match: the regex is zero-width only but find_not_empty is set")
177 }
178 CompileError::UnresolvedAstNode(ix, node) => {
179 write!(f, "Unresolved AST node encountered during analysis at position {}: {}", ix, node)
180 }
181 }
182 }
183}
184
185impl fmt::Display for RuntimeError {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 match self {
188 RuntimeError::StackOverflow => write!(f, "Max stack size exceeded for backtracking"),
189 RuntimeError::BacktrackLimitExceeded => {
190 write!(f, "Max limit for backtracking count exceeded")
191 }
192 }
193 }
194}
195
196impl fmt::Display for Error {
197 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
198 match self {
199 Error::ParseError(position, parse_error) => {
200 write!(f, "Parsing error at position {}: {}", position, parse_error)
201 }
202 Error::CompileError(compile_error) => {
203 write!(f, "Error compiling regex: {}", compile_error)
204 }
205 Error::RuntimeError(runtime_error) => {
206 write!(f, "Error executing regex: {}", runtime_error)
207 }
208 }
209 }
210}
211
212impl From<CompileError> for Error {
213 fn from(compile_error: CompileError) -> Self {
214 Error::CompileError(Box::new(compile_error))
215 }
216}