Skip to main content

moxy_token/
lib.rs

1#![cfg_attr(nightly, feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site,))]
2
3//! # Moxy tokens
4//!
5//! Token types, lexing, spans, and compiler-token conversions for Rust syntax
6//! tooling. [`TokenStream`] is an owned sequence of [`TokenTree`] values that
7//! preserves token text, punctuation spacing, and source spans.
8//!
9//! ## Quick start
10//!
11//! Parse source into a token stream, or construct individual token types with
12//! the provided macros:
13//!
14//! ```ignore
15//! use moxy::token::{ident, TokenStream};
16//! use moxy::Token;
17//!
18//! let stream: TokenStream = "fn generated() {}".parse().unwrap();
19//! let name = ident!(generated);
20//! let semi: Token![;] = Default::default();
21//! assert_eq!(name.to_string(), "generated");
22//! assert_eq!(semi.to_string(), ";");
23//! ```
24//!
25//! ## Integrations
26//!
27//! Enable `serde` to serialize supported token types. Enable `proc-macro2` for
28//! conversions with `proc_macro2`;
29
30extern crate proc_macro;
31
32mod bridge;
33mod delim;
34mod group;
35mod ident;
36mod keyword;
37mod lex;
38mod lit;
39mod punct;
40/// Source files, locations, and source maps used by spans.
41pub mod source;
42mod spacing;
43mod span;
44mod stream;
45mod tree;
46
47#[doc(inline)]
48pub use delim::*;
49#[doc(inline)]
50pub use group::*;
51#[doc(inline)]
52pub use ident::*;
53#[doc(inline)]
54pub use keyword::*;
55#[doc(inline)]
56pub use lex::*;
57#[doc(inline)]
58pub use lit::*;
59#[doc(inline)]
60pub use punct::*;
61#[doc(inline)]
62pub use source::Location;
63#[doc(inline)]
64pub use spacing::*;
65#[doc(inline)]
66pub use span::{DelimSpan, RangeSpan, Span, Spanner};
67#[doc(inline)]
68pub use stream::*;
69#[doc(inline)]
70pub use tree::*;
71
72/// Emits a value as tokens into a destination token stream.
73/// A public Rust token API type for to tokens<t.
74pub trait ToTokens<T = TokenStream> {
75    fn to_tokens(&self, tokens: &mut T);
76}
77
78/// Convenience methods for values that can emit a [`TokenStream`].
79/// A public Rust token API type for to token stream:.
80pub trait ToTokenStream: ToTokens<TokenStream> {
81    fn to_token_stream(&self) -> TokenStream {
82        let mut tokens = TokenStream::new();
83        self.to_tokens(&mut tokens);
84        tokens
85    }
86
87    fn into_token_stream(self) -> TokenStream
88    where
89        Self: Sized,
90    {
91        self.to_token_stream()
92    }
93}
94
95/// Fallibly converts a parsing input into a [`TokenStream`].
96///
97/// Unlike [`ToTokenStream`], this trait is intended for input that may need
98/// lexing, such as Rust source text.
99pub trait TryIntoTokenStream: ToTokenStream {
100    fn try_into_token_stream(self) -> Result<TokenStream, LexError>;
101}
102
103impl<X: ToTokens<TokenStream> + ?Sized> ToTokenStream for X {}
104
105impl TryIntoTokenStream for TokenStream {
106    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
107        Ok(self)
108    }
109}
110
111impl TryIntoTokenStream for &TokenStream {
112    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
113        Ok(self.clone())
114    }
115}
116
117impl TryIntoTokenStream for &&TokenStream {
118    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
119        Ok((*self).clone())
120    }
121}
122
123impl TryIntoTokenStream for &str {
124    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
125        TokenStream::from_string(self.to_string())
126    }
127}
128
129impl TryIntoTokenStream for &&str {
130    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
131        TokenStream::from_string((*self).to_string())
132    }
133}
134
135impl TryIntoTokenStream for String {
136    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
137        TokenStream::from_string(self)
138    }
139}
140
141impl TryIntoTokenStream for &String {
142    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
143        TokenStream::from_string(self.clone())
144    }
145}
146
147impl TryIntoTokenStream for &&String {
148    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
149        TokenStream::from_string((*self).clone())
150    }
151}
152
153impl<T: ToTokens> ToTokens for ::std::boxed::Box<T> {
154    fn to_tokens(&self, tokens: &mut TokenStream) {
155        (**self).to_tokens(tokens);
156    }
157}
158
159impl<T: ToTokens> ToTokens for &T {
160    fn to_tokens(&self, tokens: &mut TokenStream) {
161        ToTokens::to_tokens(*self, tokens);
162    }
163}
164
165impl<T: ToTokens> ToTokens for Option<T> {
166    fn to_tokens(&self, tokens: &mut TokenStream) {
167        if let Some(v) = self {
168            v.to_tokens(tokens);
169        }
170    }
171}
172
173impl<T: ToTokens> ToTokens for Vec<T> {
174    fn to_tokens(&self, tokens: &mut TokenStream) {
175        for v in self {
176            v.to_tokens(tokens);
177        }
178    }
179}
180
181impl<T: ToTokens, E: ToTokens> ToTokens for Result<T, E> {
182    fn to_tokens(&self, tokens: &mut TokenStream) {
183        match self {
184            Self::Ok(v) => v.to_tokens(tokens),
185            Self::Err(err) => err.to_tokens(tokens),
186        }
187    }
188}
189
190/// Map a Rust punctuation or keyword symbol to its [`crate`] token type.
191#[macro_export]
192macro_rules! Token {
193    // --- punctuation: single char ---
194    [&]     => { $crate::And };
195    [|]     => { $crate::Or };
196    [!]     => { $crate::Not };
197    [~]     => { $crate::Tilde };
198    [+]     => { $crate::Plus };
199    [-]     => { $crate::Minus };
200    [_]     => { $crate::Underscore };
201    [*]     => { $crate::Star };
202    [/]     => { $crate::Slash };
203    [%]     => { $crate::Percent };
204    [^]     => { $crate::Caret };
205    [=]     => { $crate::Eq };
206    [<]     => { $crate::Lt };
207    [>]     => { $crate::Gt };
208    [@]     => { $crate::At };
209    [.]     => { $crate::Dot };
210    [,]     => { $crate::Comma };
211    [;]     => { $crate::Semi };
212    [:]     => { $crate::Colon };
213    [#]     => { $crate::Pound };
214    [$]     => { $crate::Dollar };
215    [?]     => { $crate::Question };
216
217    // --- keywords ---
218    [as]          => { $crate::As };
219    [async]       => { $crate::Async };
220    [auto]        => { $crate::Auto };
221    [await]       => { $crate::Await };
222    [become]      => { $crate::Become };
223    [box]         => { $crate::Box };
224    [break]       => { $crate::Break };
225    [const]       => { $crate::Const };
226    [continue]    => { $crate::Continue };
227    [crate]       => { $crate::Crate };
228    [default]     => { $crate::Default };
229    [do]          => { $crate::Do };
230    [dyn]         => { $crate::Dyn };
231    [else]        => { $crate::Else };
232    [enum]        => { $crate::Enum };
233    [extern]      => { $crate::Extern };
234    [final]       => { $crate::Final };
235    [fn]          => { $crate::Fn };
236    [for]         => { $crate::For };
237    [if]          => { $crate::If };
238    [impl]        => { $crate::Impl };
239    [in]          => { $crate::In };
240    [let]         => { $crate::Let };
241    [loop]        => { $crate::Loop };
242    [macro]       => { $crate::Macro };
243    [macro_rules] => { $crate::MacroRules };
244    [match]       => { $crate::Match };
245    [mod]         => { $crate::Mod };
246    [move]        => { $crate::Move };
247    [mut]         => { $crate::Mut };
248    [override]    => { $crate::Override };
249    [priv]        => { $crate::Priv };
250    [pub]         => { $crate::Pub };
251    [raw]         => { $crate::Raw };
252    [ref]         => { $crate::Ref };
253    [return]      => { $crate::Return };
254    [safe]        => { $crate::Safe };
255    [Self]        => { $crate::SelfType };
256    [self]        => { $crate::SelfValue };
257    [static]      => { $crate::Static };
258    [struct]      => { $crate::Struct };
259    [super]       => { $crate::Super };
260    [trait]       => { $crate::Trait };
261    [try]         => { $crate::Try };
262    [type]        => { $crate::Type };
263    [typeof]      => { $crate::Typeof };
264    [union]       => { $crate::Union };
265    [unsafe]      => { $crate::Unsafe };
266    [unsized]     => { $crate::Unsized };
267    [use]         => { $crate::Use };
268    [virtual]     => { $crate::Virtual };
269    [where]       => { $crate::Where };
270    [while]       => { $crate::While };
271    [yield]       => { $crate::Yield };
272}