1#![allow(clippy::new_without_default)]
9#![allow(clippy::type_complexity)]
10#![allow(clippy::unnecessary_wraps)]
11#![allow(clippy::upper_case_acronyms)]
12#![forbid(unsafe_code)]
13#![deny(unreachable_pub)]
14
15use std::{error::Error, fmt};
16
17mod codegen;
18mod ctbuilder;
19#[doc(hidden)]
20pub mod defaults;
21mod lexer;
22mod parser;
23
24#[allow(deprecated)]
25pub use crate::{
26 ctbuilder::{
27 CTLexer, CTLexerBuilder, CTTokenMapBuilder, LexerKind, RustEdition, Visibility,
28 ct_token_map,
29 },
30 defaults::{DefaultLexeme, DefaultLexerTypes},
31 lexer::{
32 DEFAULT_LEX_FLAGS, LRNonStreamingLexer, LRNonStreamingLexerDef, LexFlags, LexerDef, Rule,
33 UNSPECIFIED_LEX_FLAGS,
34 },
35 parser::StartState,
36 parser::StartStateOperation,
37};
38
39use cfgrammar::header::{HeaderError, HeaderErrorKind};
40use cfgrammar::yacc::parser::SpansKind;
41use cfgrammar::{Span, Spanned};
42
43pub type LexBuildResult<T> = Result<T, Vec<LexBuildError>>;
44
45#[derive(Debug)]
47pub struct LexBuildError {
48 pub(crate) kind: LexErrorKind,
49 pub(crate) spans: Vec<Span>,
50}
51
52impl Error for LexBuildError {}
53
54#[derive(Debug, Clone)]
56#[non_exhaustive]
57pub enum LexErrorKind {
58 PrematureEnd,
59 RoutinesNotSupported,
60 UnknownDeclaration,
61 MissingSpace,
62 InvalidName,
63 UnknownStartState,
64 DuplicateStartState,
65 InvalidStartState,
66 InvalidStartStateName,
67 DuplicateName,
68 RegexError(regex::Error),
69 VerbatimNotSupported,
70 Header(HeaderErrorKind, SpansKind),
71}
72
73impl LexErrorKind {
74 fn is_same_kind(&self, other: &Self) -> bool {
75 use LexErrorKind as EK;
76 matches!(
77 (self, other),
78 (EK::PrematureEnd, EK::PrematureEnd)
79 | (EK::RoutinesNotSupported, EK::RoutinesNotSupported)
80 | (EK::UnknownDeclaration, EK::UnknownDeclaration)
81 | (EK::MissingSpace, EK::MissingSpace)
82 | (EK::InvalidName, EK::InvalidName)
83 | (EK::UnknownStartState, EK::UnknownStartState)
84 | (EK::DuplicateStartState, EK::DuplicateStartState)
85 | (EK::InvalidStartState, EK::InvalidStartState)
86 | (EK::InvalidStartStateName, EK::InvalidStartStateName)
87 | (EK::DuplicateName, EK::DuplicateName)
88 | (EK::RegexError(_), EK::RegexError(_))
89 | (EK::VerbatimNotSupported, EK::VerbatimNotSupported)
90 )
91 }
92}
93
94impl Spanned for LexBuildError {
95 fn spans(&self) -> &[Span] {
96 self.spans.as_slice()
97 }
98
99 fn spanskind(&self) -> SpansKind {
100 match self.kind {
101 LexErrorKind::PrematureEnd
102 | LexErrorKind::RoutinesNotSupported
103 | LexErrorKind::UnknownDeclaration
104 | LexErrorKind::MissingSpace
105 | LexErrorKind::InvalidName
106 | LexErrorKind::UnknownStartState
107 | LexErrorKind::InvalidStartState
108 | LexErrorKind::InvalidStartStateName
109 | LexErrorKind::VerbatimNotSupported
110 | LexErrorKind::RegexError(_) => SpansKind::Error,
111 LexErrorKind::DuplicateName | LexErrorKind::DuplicateStartState => {
112 SpansKind::DuplicationError
113 }
114 LexErrorKind::Header(_, spanskind) => spanskind,
115 }
116 }
117}
118
119impl fmt::Display for LexBuildError {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 let s = match &self.kind {
122 LexErrorKind::VerbatimNotSupported => "Verbatim code not supported",
123 LexErrorKind::PrematureEnd => "File ends prematurely",
124 LexErrorKind::RoutinesNotSupported => "Routines not currently supported",
125 LexErrorKind::UnknownDeclaration => "Unknown declaration",
126 LexErrorKind::MissingSpace => "Rule is missing a space",
127 LexErrorKind::InvalidName => "Invalid rule name",
128 LexErrorKind::UnknownStartState => "Start state not known",
129 LexErrorKind::DuplicateStartState => "Start state already exists",
130 LexErrorKind::InvalidStartState => "Invalid start state",
131 LexErrorKind::InvalidStartStateName => "Invalid start state name",
132 LexErrorKind::DuplicateName => "Rule name already exists",
133 LexErrorKind::RegexError(e) => return write!(f, "Invalid regular expression: {e}"),
134 LexErrorKind::Header(e, _) => return write!(f, "In '%grmtools' section {e}"),
135 };
136 write!(f, "{s}")
137 }
138}
139
140impl From<HeaderError<Span>> for LexBuildError {
141 fn from(e: HeaderError<Span>) -> LexBuildError {
142 LexBuildError {
143 kind: LexErrorKind::Header(e.kind, e.spanskind()),
144 spans: e.locations,
145 }
146 }
147}
148
149#[derive(Copy, Clone, Debug)]
150pub struct StartStateId {
151 _id: usize,
152}
153
154impl StartStateId {
155 fn new(id: usize) -> Self {
156 Self { _id: id }
157 }
158}
159
160#[derive(Clone, Debug)]
162pub struct LRLexError {
163 span: Span,
164 lexing_state: Option<StartStateId>,
165}
166
167impl lrpar::LexError for LRLexError {
168 fn span(&self) -> Span {
169 self.span
170 }
171}
172
173impl LRLexError {
174 pub fn new(span: Span) -> Self {
176 LRLexError {
177 span,
178 lexing_state: None,
179 }
180 }
181
182 pub fn new_with_lexing_state(span: Span, lexing_state: StartStateId) -> Self {
184 LRLexError {
185 span,
186 lexing_state: Some(lexing_state),
187 }
188 }
189
190 pub fn lexing_state(&self) -> Option<StartStateId> {
192 self.lexing_state
193 }
194}
195
196impl Error for LRLexError {}
197
198impl fmt::Display for LRLexError {
199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200 write!(
201 f,
202 "Couldn't lex input starting at byte {}",
203 self.span.start()
204 )
205 }
206}
207
208#[deprecated(
209 since = "0.8.0",
210 note = "This struct has been renamed to LRNonStreamingLexerDef"
211)]
212pub type NonStreamingLexerDef<StorageT> = LRNonStreamingLexerDef<StorageT>;
213
214#[macro_export]
221macro_rules! lrlex_mod {
222 ($path:expr) => {
223 include!(concat!(env!("OUT_DIR"), "/", $path, ".rs"));
224 };
225}
226
227mod unstable {
231 #![allow(unused)]
232 #![allow(unreachable_pub)]
233 pub struct UnstableApi;
234 pub trait UnstableTrait {}
235}
236
237pub mod unstable_api {
241 #[cfg(feature = "_unstable_api")]
245 pub use crate::unstable::UnstableApi;
246
247 #[cfg(feature = "_unsealed_unstable_traits")]
280 pub use crate::unstable::UnstableTrait;
281
282 pub struct InternalPublicApi;
292}