Skip to main content

moxy_token/parser/
error.rs

1use crate::Token;
2use crate::span::DelimSpan;
3use crate::{Delim, Group, Ident, LexError, Lit, Punctuation, Span, ToTokenStream, ToTokens, TokenStream};
4
5#[derive(Debug, Clone)]
6pub struct ParseError {
7    span: Span,
8    message: String,
9    children: Vec<Self>,
10}
11
12impl ParseError {
13    pub fn new(span: Span, message: impl std::fmt::Display) -> Self {
14        Self {
15            span,
16            message: message.to_string(),
17            children: vec![],
18        }
19    }
20
21    pub fn span(&self) -> Span {
22        self.span
23    }
24
25    pub fn message(&self) -> &str {
26        &self.message
27    }
28
29    pub fn children(&self) -> &[Self] {
30        &self.children
31    }
32
33    /// Combine two errors, appending `other` as a child of `self`.
34    pub fn combine(mut self, other: Self) -> Self {
35        self.children.push(other);
36        self
37    }
38
39    pub fn to_compile_error(&self) -> TokenStream {
40        let span = self.span;
41        let ident = Ident::new("compile_error").with_span(span);
42        let bang = <Token![!]>::new(span);
43        let mut lit = Lit::string(&self.message);
44        lit.set_span(span);
45
46        let mut group = Group::new(Delim::Paren, lit.into_token_tree().into_token_stream());
47        group.set_span(DelimSpan::new(span, span));
48
49        vec![
50            ident.into_token_tree(),
51            Punctuation::from(bang).into_token_tree(),
52            group.into_token_tree(),
53            Punctuation::from(<Token![;]>::new(span)).into_token_tree(),
54        ]
55        .into_token_stream()
56    }
57}
58
59impl From<LexError> for ParseError {
60    fn from(e: LexError) -> Self {
61        Self::new(e.span(), e)
62    }
63}
64
65impl std::fmt::Display for ParseError {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        write!(f, "{}", self.message)?;
68
69        for child in &self.children {
70            write!(f, "\n{}", child)?;
71        }
72
73        Ok(())
74    }
75}
76
77impl std::error::Error for ParseError {}
78
79impl ToTokens for ParseError {
80    fn to_tokens(&self, tokens: &mut TokenStream) {
81        self.to_compile_error().to_tokens(tokens);
82    }
83}
84
85impl<T: ToTokens, E: ToTokens> ToTokens for Result<T, E> {
86    fn to_tokens(&self, tokens: &mut TokenStream) {
87        match self {
88            Self::Ok(v) => v.to_tokens(tokens),
89            Self::Err(err) => err.to_tokens(tokens),
90        }
91    }
92}