moxy_token/parser/
error.rs1use 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 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}