futures_await_synom/
tokens.rs

1//! Discrete tokens that can be parsed out by synom.
2//!
3//! This module contains a number of useful tokens like `+=` and `/` along with
4//! keywords like `crate` and such. These structures are used to track the spans
5//! of these tokens and all implment the `ToTokens` and `Synom` traits when the
6//! corresponding feature is activated.
7
8use span::Span;
9
10macro_rules! tokens {
11    (
12        ops: {
13            $(($($op:tt)*),)*
14        }
15        delim: {
16            $(($($delim:tt)*),)*
17        }
18        syms: {
19            $(($($sym:tt)*),)*
20        }
21    ) => (
22        $(op! { $($op)* })*
23        $(delim! { $($delim)* })*
24        $(sym! { $($sym)* })*
25    )
26}
27
28macro_rules! op {
29    (pub struct $name:ident($($contents:tt)*) => $s:expr) => {
30        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
31        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
32        #[derive(Default)]
33        pub struct $name(pub $($contents)*);
34
35        #[cfg(feature = "printing")]
36        impl ::quote::ToTokens for $name {
37            fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
38                printing::op($s, &self.0, tokens);
39            }
40        }
41
42        #[cfg(feature = "parsing")]
43        impl ::Synom for $name {
44            fn parse(tokens: $crate::Cursor) -> $crate::PResult<$name> {
45                parsing::op($s, tokens, $name)
46            }
47        }
48    }
49}
50
51macro_rules! sym {
52    (pub struct $name:ident => $s:expr) => {
53        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
54        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
55        #[derive(Default)]
56        pub struct $name(pub Span);
57
58        #[cfg(feature = "printing")]
59        impl ::quote::ToTokens for $name {
60            fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
61                printing::sym($s, &self.0, tokens);
62            }
63        }
64
65        #[cfg(feature = "parsing")]
66        impl ::Synom for $name {
67            fn parse(tokens: $crate::Cursor) -> $crate::PResult<$name> {
68                parsing::sym($s, tokens, $name)
69            }
70        }
71    }
72}
73
74macro_rules! delim {
75    (pub struct $name:ident => $s:expr) => {
76        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
77        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
78        #[derive(Default)]
79        pub struct $name(pub Span);
80
81        impl $name {
82            #[cfg(feature = "printing")]
83            pub fn surround<F>(&self,
84                               tokens: &mut ::quote::Tokens,
85                               f: F)
86                where F: FnOnce(&mut ::quote::Tokens)
87            {
88                printing::delim($s, &self.0, tokens, f);
89            }
90
91            #[cfg(feature = "parsing")]
92            pub fn parse<F, R>(tokens: $crate::Cursor, f: F) -> $crate::PResult<(R, $name)>
93                where F: FnOnce($crate::Cursor) -> $crate::PResult<R>
94            {
95                parsing::delim($s, tokens, $name, f)
96            }
97        }
98    }
99}
100
101tokens! {
102    ops: {
103        (pub struct Add([Span; 1])          => "+"),
104        (pub struct AddEq([Span; 2])        => "+="),
105        (pub struct And([Span; 1])          => "&"),
106        (pub struct AndAnd([Span; 2])       => "&&"),
107        (pub struct AndEq([Span; 2])        => "&="),
108        (pub struct At([Span; 1])           => "@"),
109        (pub struct Bang([Span; 1])         => "!"),
110        (pub struct Caret([Span; 1])        => "^"),
111        (pub struct CaretEq([Span; 2])      => "^="),
112        (pub struct Colon([Span; 1])        => ":"),
113        (pub struct Colon2([Span; 2])       => "::"),
114        (pub struct Comma([Span; 1])        => ","),
115        (pub struct Div([Span; 1])          => "/"),
116        (pub struct DivEq([Span; 2])        => "/="),
117        (pub struct Dot([Span; 1])          => "."),
118        (pub struct Dot2([Span; 2])         => ".."),
119        (pub struct Dot3([Span; 3])         => "..."),
120        (pub struct Eq([Span; 1])           => "="),
121        (pub struct EqEq([Span; 2])         => "=="),
122        (pub struct Ge([Span; 2])           => ">="),
123        (pub struct Gt([Span; 1])           => ">"),
124        (pub struct Le([Span; 2])           => "<="),
125        (pub struct Lt([Span; 1])           => "<"),
126        (pub struct MulEq([Span; 2])        => "*="),
127        (pub struct Ne([Span; 2])           => "!="),
128        (pub struct Or([Span; 1])           => "|"),
129        (pub struct OrEq([Span; 2])         => "|="),
130        (pub struct OrOr([Span; 2])         => "||"),
131        (pub struct Pound([Span; 1])        => "#"),
132        (pub struct Question([Span; 1])     => "?"),
133        (pub struct RArrow([Span; 2])       => "->"),
134        (pub struct LArrow([Span; 2])       => "<-"),
135        (pub struct Rem([Span; 1])          => "%"),
136        (pub struct RemEq([Span; 2])        => "%="),
137        (pub struct Rocket([Span; 2])       => "=>"),
138        (pub struct Semi([Span; 1])         => ";"),
139        (pub struct Shl([Span; 2])          => "<<"),
140        (pub struct ShlEq([Span; 3])        => "<<="),
141        (pub struct Shr([Span; 2])          => ">>"),
142        (pub struct ShrEq([Span; 3])        => ">>="),
143        (pub struct Star([Span; 1])         => "*"),
144        (pub struct Sub([Span; 1])          => "-"),
145        (pub struct SubEq([Span; 2])        => "-="),
146        (pub struct Underscore([Span; 1])   => "_"),
147    }
148    delim: {
149        (pub struct Brace                   => "{"),
150        (pub struct Bracket                 => "["),
151        (pub struct Paren                   => "("),
152        (pub struct Group                   => " "),
153    }
154    syms: {
155        (pub struct As                      => "as"),
156        (pub struct Box_                    => "box"),
157        (pub struct Break                   => "break"),
158        (pub struct CapSelf                 => "Self"),
159        (pub struct Catch                   => "catch"),
160        (pub struct Const                   => "const"),
161        (pub struct Continue                => "continue"),
162        (pub struct Crate                   => "crate"),
163        (pub struct Default_                => "default"),
164        (pub struct Do                      => "do"),
165        (pub struct Else                    => "else"),
166        (pub struct Enum                    => "enum"),
167        (pub struct Extern                  => "extern"),
168        (pub struct Fn_                     => "fn"),
169        (pub struct For                     => "for"),
170        (pub struct If                      => "if"),
171        (pub struct Impl                    => "impl"),
172        (pub struct In                      => "in"),
173        (pub struct Let                     => "let"),
174        (pub struct Loop                    => "loop"),
175        (pub struct Match                   => "match"),
176        (pub struct Mod                     => "mod"),
177        (pub struct Move                    => "move"),
178        (pub struct Mut                     => "mut"),
179        (pub struct Pub                     => "pub"),
180        (pub struct Ref                     => "ref"),
181        (pub struct Return                  => "return"),
182        (pub struct Self_                   => "self"),
183        (pub struct Static                  => "static"),
184        (pub struct Struct                  => "struct"),
185        (pub struct Super                   => "super"),
186        (pub struct Trait                   => "trait"),
187        (pub struct Type                    => "type"),
188        (pub struct Union                   => "union"),
189        (pub struct Unsafe                  => "unsafe"),
190        (pub struct Use                     => "use"),
191        (pub struct Where                   => "where"),
192        (pub struct While                   => "while"),
193        (pub struct Yield                   => "yield"),
194    }
195}
196
197#[cfg(feature = "parsing")]
198mod parsing {
199    use proc_macro2::{Delimiter, Spacing};
200
201    use {PResult, Cursor, parse_error};
202    use span::Span;
203
204    pub trait FromSpans: Sized {
205        fn from_spans(spans: &[Span]) -> Self;
206    }
207
208    impl FromSpans for [Span; 1] {
209        fn from_spans(spans: &[Span]) -> Self {
210            [spans[0]]
211        }
212    }
213
214    impl FromSpans for [Span; 2] {
215        fn from_spans(spans: &[Span]) -> Self {
216            [spans[0], spans[1]]
217        }
218    }
219
220    impl FromSpans for [Span; 3] {
221        fn from_spans(spans: &[Span]) -> Self {
222            [spans[0], spans[1], spans[2]]
223        }
224    }
225
226    pub fn op<'a, T, R>(s: &str,
227                        mut tokens: Cursor<'a>,
228                        new: fn(T) -> R)
229            -> PResult<'a, R>
230        where T: FromSpans,
231    {
232        let mut spans = [Span::default(); 3];
233        assert!(s.len() <= spans.len());
234        let chars = s.chars();
235
236        for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
237            match tokens.op() {
238                Some((rest, span, c, kind)) if c == ch => {
239                    if i != s.len() - 1 {
240                        match kind {
241                            Spacing::Joint => {}
242                            _ => return parse_error(),
243                        }
244                    }
245                    *slot = Span(span);
246                    tokens = rest;
247                }
248                _ => return parse_error()
249            }
250        }
251        Ok((tokens, new(T::from_spans(&spans))))
252    }
253
254    pub fn sym<'a, T>(sym: &str,
255                      tokens: Cursor<'a>,
256                      new: fn(Span) -> T)
257        -> PResult<'a, T>
258    {
259        if let Some((rest, span, s)) = tokens.word() {
260            if s.as_str() == sym {
261                return Ok((rest, new(Span(span))));
262            }
263        }
264        parse_error()
265    }
266
267    pub fn delim<'a, F, R, T>(delim: &str,
268                              tokens: Cursor<'a>,
269                              new: fn(Span) -> T,
270                              f: F)
271        -> PResult<'a, (R, T)>
272        where F: FnOnce(Cursor) -> PResult<R>
273    {
274        // NOTE: We should support none-delimited sequences here.
275        let delim = match delim {
276            "(" => Delimiter::Parenthesis,
277            "{" => Delimiter::Brace,
278            "[" => Delimiter::Bracket,
279            " " => Delimiter::None,
280            _ => panic!("unknown delimiter: {}", delim),
281        };
282
283        if let Some(seqinfo) = tokens.seq(delim) {
284            match f(seqinfo.inside) {
285                Ok((remaining, ret)) => {
286                    if remaining.eof() {
287                        return Ok((seqinfo.outside, (ret, new(Span(seqinfo.span)))));
288                    }
289                }
290                Err(err) => return Err(err),
291            }
292        }
293        parse_error()
294    }
295}
296
297#[cfg(feature = "printing")]
298mod printing {
299    use proc_macro2::{TokenTree, TokenNode, Spacing, Term};
300    use quote::Tokens;
301
302    use span::Span;
303
304    pub fn op(s: &str, spans: &[Span], tokens: &mut Tokens) {
305        assert_eq!(s.len(), spans.len());
306
307        let mut chars = s.chars();
308        let mut spans = spans.iter();
309        let ch = chars.next_back().unwrap();
310        let span = spans.next_back().unwrap();
311        for (ch, span) in chars.zip(spans) {
312            tokens.append(TokenTree {
313                span: span.0,
314                kind: TokenNode::Op(ch, Spacing::Joint),
315            });
316        }
317
318        tokens.append(TokenTree {
319            span: span.0,
320            kind: TokenNode::Op(ch, Spacing::Alone),
321        });
322    }
323
324    pub fn sym(s: &str, span: &Span, tokens: &mut Tokens) {
325        tokens.append(TokenTree {
326            span: span.0,
327            kind: TokenNode::Term(Term::intern(s)),
328        });
329    }
330
331    pub fn delim<F>(s: &str, span: &Span, tokens: &mut Tokens, f: F)
332        where F: FnOnce(&mut Tokens)
333    {
334        tokens.append_delimited(s, span.0, f)
335    }
336}