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