1#![doc(hidden)]
4
5use std::borrow::Cow;
6
7#[cfg(not(feature = "testing"))]
8extern crate proc_macro;
9
10#[cfg(not(feature = "testing"))]
11pub mod pm {
12 pub use proc_macro::{
13 token_stream, Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream,
14 TokenTree,
15 };
16 pub trait ToTokens {
17 fn to_tokens(&self, tokens: &mut TokenStream);
18 fn to_token_stream(&self) -> TokenStream {
19 let mut tokens = TokenStream::new();
20 self.to_tokens(&mut tokens);
21 tokens
22 }
23 fn into_token_stream(self) -> TokenStream
24 where
25 Self: Sized,
26 {
27 self.to_token_stream()
28 }
29 }
30 impl ToTokens for Group {
31 fn to_tokens(&self, tokens: &mut TokenStream) {
32 tokens.extend([TokenTree::from(self.clone())]);
33 }
34 }
35 impl ToTokens for Ident {
36 fn to_tokens(&self, tokens: &mut TokenStream) {
37 tokens.extend([TokenTree::from(self.clone())]);
38 }
39 }
40 impl ToTokens for Punct {
41 fn to_tokens(&self, tokens: &mut TokenStream) {
42 tokens.extend([TokenTree::from(self.clone())]);
43 }
44 }
45 impl ToTokens for Literal {
46 fn to_tokens(&self, tokens: &mut TokenStream) {
47 tokens.extend([TokenTree::from(self.clone())]);
48 }
49 }
50 impl ToTokens for TokenTree {
51 fn to_tokens(&self, tokens: &mut TokenStream) {
52 tokens.extend([self.clone()]);
53 }
54 }
55}
56
57#[cfg(feature = "testing")]
58pub mod pm {
59 pub use proc_macro2::{
60 token_stream, Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream,
61 TokenTree,
62 };
63 pub use quote::ToTokens;
64}
65
66pub struct Error {
67 pub span: pm::Span,
68 pub msg: Cow<'static, str>,
69 pub note: Option<Note>,
70}
71
72pub struct Note {
73 pub span: Option<pm::Span>,
74 pub msg: Cow<'static, str>,
75}
76
77impl pm::ToTokens for Error {
78 fn to_tokens(&self, tokens: &mut pm::TokenStream) {
79 fn ensure_lf(buf: &mut String, s: &str) {
80 if s.ends_with('\n') {
81 buf.push_str(s);
82 } else {
83 buf.push_str(s);
84 buf.push('\n');
85 }
86 }
87
88 let mut message = String::new();
89 ensure_lf(&mut message, &self.msg);
90 message.push('\n');
91
92 if let Some(note) = self.note.as_ref() {
93 message.push_str(" = note: ");
94 ensure_lf(&mut message, ¬e.msg);
95 }
96 message.push('\n');
97
98 let mut msg = pm::Literal::string(&message);
99 msg.set_span(self.span);
100 let mut group = pm::Group::new(pm::Delimiter::Brace, msg.into_token_stream());
101 group.set_span(self.span);
102
103 pm::Ident::new("compile_error", self.span).to_tokens(tokens);
104 let mut exclamation = pm::Punct::new('!', pm::Spacing::Alone);
105 exclamation.set_span(self.span);
106 exclamation.to_tokens(tokens);
107 group.to_tokens(tokens);
108 }
109}
110
111pub mod consts;
112pub mod egroup;
113pub mod exec;
114pub mod funcs;
115pub mod parse;
116pub mod rules;
117pub mod state;
118pub mod utils;