1#![deny(missing_docs)]
2
3use std::{path::PathBuf, rc::Rc, sync::Arc};
9
10use thiserror::Error;
11
12#[cfg(feature = "derive")]
13pub use token_parser_derive::{Parsable, SymbolParsable};
14
15pub trait Context {
20 #[cfg(feature = "radix-parsing")]
21 #[inline]
22 fn radix(&self) -> u32 {
24 10
25 }
26}
27
28impl Context for () {}
29
30#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
32pub struct Span {
33 pub line: usize,
35 pub column: usize,
37 pub start: usize,
39 pub end: usize,
41}
42
43impl std::fmt::Display for Span {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "{}:{}", self.line + 1, self.column + 1)
46 }
47}
48
49#[derive(Debug, Error)]
51#[non_exhaustive]
52pub enum ErrorKind {
53 #[error("Not enough elements: at least {0} expected")]
55 NotEnoughElements(usize),
56
57 #[error("Too many elements: {0} unexpected")]
59 TooManyElements(usize),
60
61 #[error("List not allowed")]
63 ListNotAllowed,
64
65 #[error("Symbol not allowed")]
67 SymbolNotAllowed,
68
69 #[error("Expected {type_name}: {source}")]
71 StringParsing {
72 type_name: &'static str,
74 #[source]
76 source: Box<dyn std::error::Error + Send + Sync>,
77 },
78
79 #[error("Unknown field {0}")]
81 UnknownField(Box<str>),
82
83 #[error("Invalid element")]
85 InvalidElement,
86}
87
88#[derive(Debug)]
90pub struct Error {
91 pub kind: ErrorKind,
93 pub span: Option<Span>,
95 pub context: Option<Box<str>>,
97}
98
99impl std::fmt::Display for Error {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 if let Some(span) = self.span {
102 write!(f, "{span}: ")?;
103 }
104 if let Some(ctx) = &self.context {
105 write!(f, "{ctx}: ")?;
106 }
107 write!(f, "{}", self.kind)
108 }
109}
110
111impl std::error::Error for Error {}
112
113impl From<ErrorKind> for Error {
114 fn from(kind: ErrorKind) -> Self {
115 Self {
116 kind,
117 span: None,
118 context: None,
119 }
120 }
121}
122
123impl Error {
124 #[must_use]
126 pub const fn at(mut self, span: Span) -> Self {
127 if self.span.is_none() {
128 self.span = Some(span);
129 }
130 self
131 }
132
133 pub fn context(mut self, msg: impl Into<Box<str>>) -> Self {
135 if self.context.is_none() {
136 self.context = Some(msg.into());
137 }
138 self
139 }
140}
141
142pub type Result<T> = std::result::Result<T, Error>;
144
145#[derive(Clone)]
147pub enum Unit {
148 Symbol(Box<str>, Span),
150 Parser(Parser),
152}
153
154impl Unit {
155 #[must_use]
157 pub const fn span(&self) -> Span {
158 match self {
159 Self::Symbol(_, span) => *span,
160 Self::Parser(parser) => parser.span,
161 }
162 }
163
164 pub fn symbol(self) -> Result<Box<str>> {
170 match self {
171 Self::Symbol(name, _) => Ok(name),
172 Self::Parser(parser) => Err(Error::from(ErrorKind::ListNotAllowed).at(parser.span)),
173 }
174 }
175
176 pub fn parser(self) -> Result<Parser> {
182 match self {
183 Self::Parser(parser) => Ok(parser),
184 Self::Symbol(_, span) => Err(Error::from(ErrorKind::SymbolNotAllowed).at(span)),
185 }
186 }
187
188 pub fn substitute(&mut self, variable: &str, value: &str) {
190 match self {
191 Self::Symbol(name, _) => {
192 if name.as_ref() == variable {
193 *name = value.into();
194 }
195 }
196 Self::Parser(parser) => parser.substitute(variable, value),
197 }
198 }
199}
200
201impl<C: Context> Parsable<C> for Unit {
202 fn parse_symbol(name: Box<str>, span: Span, _context: &C) -> Result<Self> {
203 Ok(Self::Symbol(name, span))
204 }
205
206 fn parse_list(parser: &mut Parser, _context: &C) -> Result<Self> {
207 let form = std::mem::take(&mut parser.form);
208 let span = parser.span;
209 Ok(Self::Parser(Parser {
210 form,
211 count: 0,
212 span,
213 }))
214 }
215}
216
217#[expect(clippy::boxed_local)]
219pub trait Parsable<C: Context>: Sized {
220 fn parse_symbol(_name: Box<str>, _span: Span, _context: &C) -> Result<Self> {
227 Err(ErrorKind::SymbolNotAllowed.into())
228 }
229
230 fn parse_list(_parser: &mut Parser, _context: &C) -> Result<Self> {
237 Err(ErrorKind::ListNotAllowed.into())
238 }
239}
240
241pub trait Unparsable<C: Context> {
246 fn to_unit(&self, context: &C) -> Unit;
248}
249
250fn parse<C: Context, P: Parsable<C>>(unit: Unit, context: &C) -> Result<P> {
251 match unit {
252 Unit::Symbol(name, span) => {
253 Parsable::parse_symbol(name, span, context).map_err(|e| e.at(span))
254 }
255 Unit::Parser(mut parser) => {
256 let span = parser.span;
257 Parsable::parse_list(&mut parser, context).map_err(|e| e.at(span))
258 }
259 }
260}
261
262impl<C: Context, T: Parsable<C>> Parsable<C> for Box<T> {
263 fn parse_symbol(name: Box<str>, span: Span, context: &C) -> Result<Self> {
264 Ok(Self::new(Parsable::parse_symbol(name, span, context)?))
265 }
266
267 fn parse_list(parser: &mut Parser, context: &C) -> Result<Self> {
268 Ok(Self::new(parser.parse_list(context)?))
269 }
270}
271
272impl<C: Context, T: Parsable<C>> Parsable<C> for Rc<T> {
273 fn parse_symbol(name: Box<str>, span: Span, context: &C) -> Result<Self> {
274 Ok(Self::new(Parsable::parse_symbol(name, span, context)?))
275 }
276
277 fn parse_list(parser: &mut Parser, context: &C) -> Result<Self> {
278 Ok(Self::new(parser.parse_list(context)?))
279 }
280}
281
282impl<C: Context, T: Parsable<C>> Parsable<C> for Arc<T> {
283 fn parse_symbol(name: Box<str>, span: Span, context: &C) -> Result<Self> {
284 Ok(Self::new(Parsable::parse_symbol(name, span, context)?))
285 }
286
287 fn parse_list(parser: &mut Parser, context: &C) -> Result<Self> {
288 Ok(Self::new(parser.parse_list(context)?))
289 }
290}
291
292impl<C: Context, T: Parsable<C>> Parsable<C> for Vec<T> {
293 fn parse_list(parser: &mut Parser, context: &C) -> Result<Self> {
294 let Parser { form, count, .. } = parser;
295 form.drain(..)
296 .rev()
297 .map(|unit| {
298 *count += 1;
299 parse(unit, context)
300 })
301 .collect()
302 }
303}
304
305impl<C: Context> Parsable<C> for String {
306 fn parse_symbol(name: Box<str>, _span: Span, _context: &C) -> Result<Self> {
307 Ok(name.into())
308 }
309}
310
311impl<C: Context> Parsable<C> for Box<str> {
312 fn parse_symbol(name: Box<str>, _span: Span, _context: &C) -> Result<Self> {
313 Ok(name)
314 }
315}
316
317impl<C: Context> Parsable<C> for PathBuf {
318 fn parse_symbol(name: Box<str>, _span: Span, _context: &C) -> Result<Self> {
319 Ok(name.as_ref().into())
320 }
321}
322
323impl<C: Context, T: Unparsable<C> + ?Sized> Unparsable<C> for Box<T> {
324 fn to_unit(&self, context: &C) -> Unit {
325 (**self).to_unit(context)
326 }
327}
328
329impl<C: Context, T: Unparsable<C> + ?Sized> Unparsable<C> for Rc<T> {
330 fn to_unit(&self, context: &C) -> Unit {
331 (**self).to_unit(context)
332 }
333}
334
335impl<C: Context, T: Unparsable<C> + ?Sized> Unparsable<C> for Arc<T> {
336 fn to_unit(&self, context: &C) -> Unit {
337 (**self).to_unit(context)
338 }
339}
340
341impl<C: Context, T: Unparsable<C>> Unparsable<C> for Vec<T> {
342 fn to_unit(&self, context: &C) -> Unit {
343 let items: Vec<Unit> = self.iter().map(|item| item.to_unit(context)).collect();
344 Unit::Parser(Parser::new(items))
345 }
346}
347
348impl<C: Context> Unparsable<C> for String {
349 fn to_unit(&self, _context: &C) -> Unit {
350 Unit::Symbol(self.clone().into_boxed_str(), Span::default())
351 }
352}
353
354impl<C: Context> Unparsable<C> for str {
355 fn to_unit(&self, _context: &C) -> Unit {
356 Unit::Symbol(self.into(), Span::default())
357 }
358}
359
360impl<C: Context> Unparsable<C> for PathBuf {
361 fn to_unit(&self, _context: &C) -> Unit {
362 Unit::Symbol(self.to_string_lossy().into(), Span::default())
363 }
364}
365
366#[macro_export]
368macro_rules! derive_symbol_parsable {
369 ($t:ty) => {
370 impl<C: $crate::Context> $crate::Parsable<C> for $t {
371 fn parse_symbol(name: Box<str>, _span: $crate::Span, _context: &C) -> $crate::Result<Self> {
372 name.parse().map_err(|error| $crate::ErrorKind::StringParsing {
373 type_name: stringify!($t),
374 source: Box::new(error),
375 }.into())
376 }
377 }
378 };
379 ($t:ty, $($rest:ty),+) => {
380 derive_symbol_parsable!($t);
381 derive_symbol_parsable!($($rest),+);
382 };
383}
384
385#[macro_export]
387macro_rules! derive_symbol_unparsable {
388 ($t:ty) => {
389 impl<C: $crate::Context> $crate::Unparsable<C> for $t {
390 fn to_unit(&self, _context: &C) -> $crate::Unit {
391 $crate::Unit::Symbol(
392 ::std::string::ToString::to_string(self).into(),
393 $crate::Span::default(),
394 )
395 }
396 }
397 };
398 ($t:ty, $($rest:ty),+) => {
399 derive_symbol_unparsable!($t);
400 derive_symbol_unparsable!($($rest),+);
401 };
402}
403
404#[cfg(not(feature = "radix-parsing"))]
405mod numbers;
406derive_symbol_parsable!(bool);
407derive_symbol_unparsable!(bool);
408derive_symbol_unparsable!(i8, i16, i32, i64, i128);
409derive_symbol_unparsable!(u8, u16, u32, u64, u128);
410derive_symbol_unparsable!(f32, f64);
411derive_symbol_unparsable!(usize);
412
413#[derive(Clone)]
415pub struct Parser {
416 form: Vec<Unit>,
417 count: usize,
418 span: Span,
419}
420
421impl Parser {
422 pub fn new<I: IntoIterator>(form: I) -> Self
424 where
425 I::Item: Into<Unit>,
426 {
427 let mut form: Vec<_> = form.into_iter().map(I::Item::into).collect();
428 form.reverse();
429 Self {
430 form,
431 count: 0,
432 span: Span::default(),
433 }
434 }
435
436 #[must_use]
438 pub const fn with_span(mut self, span: Span) -> Self {
439 self.span = span;
440 self
441 }
442
443 #[must_use]
445 pub const fn span(&self) -> Span {
446 self.span
447 }
448
449 #[must_use]
451 pub const fn is_empty(&self) -> bool {
452 self.form.is_empty()
453 }
454
455 #[must_use]
457 pub const fn len(&self) -> usize {
458 self.form.len()
459 }
460
461 pub fn substitute(&mut self, variable: &str, value: &str) {
463 for unit in &mut self.form {
464 unit.substitute(variable, value);
465 }
466 }
467
468 pub fn next_unit(&mut self) -> Option<Unit> {
470 self.count += 1;
471 self.form.pop()
472 }
473
474 pub fn parse_next<C: Context, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
481 self.count += 1;
482 if let Some(token) = self.form.pop() {
483 parse(token, context)
484 } else {
485 Result::Err(Error {
486 kind: ErrorKind::NotEnoughElements(self.count),
487 span: Some(self.span),
488 context: None,
489 })
490 }
491 }
492
493 pub fn parse_next_optional<C: Context, T: Parsable<C>>(
499 &mut self,
500 context: &C,
501 ) -> Result<Option<T>> {
502 if Self::is_empty(self) {
503 Ok(None)
504 } else {
505 self.parse_next(context).map(Some)
506 }
507 }
508
509 pub fn parse_rest<C: Context, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
518 let result = self.parse_list(context);
519 let count = self.form.len();
520 if count > 0 {
521 self.form.clear();
522 result?;
523 Err(Error {
524 kind: ErrorKind::TooManyElements(count),
525 span: Some(self.span),
526 context: None,
527 })
528 } else {
529 result
530 }
531 }
532
533 pub fn parse_list<C: Context, T: Parsable<C>>(&mut self, context: &C) -> Result<T> {
539 Parsable::parse_list(self, context)
540 }
541}
542
543impl Iterator for Parser {
544 type Item = Result<Self>;
545
546 fn next(&mut self) -> Option<Result<Self>> {
547 self.count += 1;
548 Some(self.form.pop()?.parser())
549 }
550
551 fn size_hint(&self) -> (usize, Option<usize>) {
552 let remaining = self.form.len();
553 (remaining, Some(remaining))
554 }
555}
556
557#[cfg(feature = "radix-parsing")]
558pub mod radix;