blob: 655d2a7ffdf0c326e7d65ec778e261986ba2bc91 [file] [log] [blame]
Alex Crichton954046c2017-05-30 21:49:42 -07001//! 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
Alex Crichton7b9e02f2017-05-30 15:54:33 -07008use 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 {
Michael Layzell760fd662017-05-31 22:46:05 -040044 fn parse(tokens: $crate::Cursor) -> $crate::PResult<$name> {
Alex Crichton7b9e02f2017-05-30 15:54:33 -070045 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 {
Michael Layzell760fd662017-05-31 22:46:05 -040067 fn parse(tokens: $crate::Cursor) -> $crate::PResult<$name> {
Alex Crichton7b9e02f2017-05-30 15:54:33 -070068 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")]
Michael Layzell760fd662017-05-31 22:46:05 -040092 pub fn parse<F, R>(tokens: $crate::Cursor, f: F) -> $crate::PResult<(R, $name)>
93 where F: FnOnce($crate::Cursor) -> $crate::PResult<R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -070094 {
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]) => "->"),
Michael Layzellb78f3b52017-06-04 19:03:03 -0400134 (pub struct LArrow([Span; 2]) => "<-"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700135 (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 => "("),
Michael Layzell93c36282017-06-04 20:43:14 -0400152 (pub struct Group => " "),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700153 }
154 syms: {
155 (pub struct As => "as"),
Alex Crichton954046c2017-05-30 21:49:42 -0700156 (pub struct Box_ => "box"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700157 (pub struct Break => "break"),
Alex Crichton954046c2017-05-30 21:49:42 -0700158 (pub struct CapSelf => "Self"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700159 (pub struct Catch => "catch"),
160 (pub struct Const => "const"),
161 (pub struct Continue => "continue"),
162 (pub struct Crate => "crate"),
Alex Crichton954046c2017-05-30 21:49:42 -0700163 (pub struct Default_ => "default"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700164 (pub struct Do => "do"),
165 (pub struct Else => "else"),
166 (pub struct Enum => "enum"),
167 (pub struct Extern => "extern"),
Alex Crichton954046c2017-05-30 21:49:42 -0700168 (pub struct Fn_ => "fn"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700169 (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"),
Alex Crichton954046c2017-05-30 21:49:42 -0700185 (pub struct Super => "super"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700186 (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 }
194}
195
196#[cfg(feature = "parsing")]
197mod parsing {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700198 use proc_macro2::{Delimiter, Spacing};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700199
Michael Layzell760fd662017-05-31 22:46:05 -0400200 use {PResult, Cursor, parse_error};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700201 use span::Span;
202
203 pub trait FromSpans: Sized {
204 fn from_spans(spans: &[Span]) -> Self;
205 }
206
207 impl FromSpans for [Span; 1] {
208 fn from_spans(spans: &[Span]) -> Self {
209 [spans[0]]
210 }
211 }
212
213 impl FromSpans for [Span; 2] {
214 fn from_spans(spans: &[Span]) -> Self {
215 [spans[0], spans[1]]
216 }
217 }
218
219 impl FromSpans for [Span; 3] {
220 fn from_spans(spans: &[Span]) -> Self {
221 [spans[0], spans[1], spans[2]]
222 }
223 }
224
225 pub fn op<'a, T, R>(s: &str,
Michael Layzell0a1a6632017-06-02 18:07:43 -0400226 mut tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700227 new: fn(T) -> R)
Michael Layzell760fd662017-05-31 22:46:05 -0400228 -> PResult<'a, R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700229 where T: FromSpans,
230 {
231 let mut spans = [Span::default(); 3];
Alex Crichton954046c2017-05-30 21:49:42 -0700232 assert!(s.len() <= spans.len());
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700233 let chars = s.chars();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700234
Alex Crichton954046c2017-05-30 21:49:42 -0700235 for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400236 match tokens.op() {
237 Some((rest, span, c, kind)) if c == ch => {
238 if i != s.len() - 1 {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700239 match kind {
240 Spacing::Joint => {}
241 _ => return parse_error(),
Michael Layzell0a1a6632017-06-02 18:07:43 -0400242 }
243 }
244 *slot = Span(span);
245 tokens = rest;
Alex Crichton954046c2017-05-30 21:49:42 -0700246 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400247 _ => return parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700248 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700249 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400250 Ok((tokens, new(T::from_spans(&spans))))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700251 }
252
253 pub fn sym<'a, T>(sym: &str,
Michael Layzell760fd662017-05-31 22:46:05 -0400254 tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700255 new: fn(Span) -> T)
Michael Layzell760fd662017-05-31 22:46:05 -0400256 -> PResult<'a, T>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700257 {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400258 if let Some((rest, span, s)) = tokens.word() {
259 if s.as_str() == sym {
260 return Ok((rest, new(Span(span))));
261 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700262 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400263 parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700264 }
265
266 pub fn delim<'a, F, R, T>(delim: &str,
Michael Layzell760fd662017-05-31 22:46:05 -0400267 tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700268 new: fn(Span) -> T,
269 f: F)
Michael Layzell760fd662017-05-31 22:46:05 -0400270 -> PResult<'a, (R, T)>
271 where F: FnOnce(Cursor) -> PResult<R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700272 {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400273 // NOTE: We should support none-delimited sequences here.
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700274 let delim = match delim {
275 "(" => Delimiter::Parenthesis,
276 "{" => Delimiter::Brace,
277 "[" => Delimiter::Bracket,
Michael Layzell93c36282017-06-04 20:43:14 -0400278 " " => Delimiter::None,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700279 _ => panic!("unknown delimiter: {}", delim),
280 };
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700281
Michael Layzell0a1a6632017-06-02 18:07:43 -0400282 if let Some(seqinfo) = tokens.seq(delim) {
283 match f(seqinfo.inside) {
284 Ok((remaining, ret)) => {
285 if remaining.eof() {
286 return Ok((seqinfo.outside, (ret, new(Span(seqinfo.span)))));
287 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700288 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400289 Err(err) => return Err(err),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700290 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700291 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400292 parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700293 }
294}
295
296#[cfg(feature = "printing")]
297mod printing {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700298 use proc_macro2::{TokenTree, TokenNode, Spacing, Term};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700299 use quote::Tokens;
300
301 use span::Span;
302
303 pub fn op(s: &str, spans: &[Span], tokens: &mut Tokens) {
304 assert_eq!(s.len(), spans.len());
305
306 let mut chars = s.chars();
307 let mut spans = spans.iter();
308 let ch = chars.next_back().unwrap();
309 let span = spans.next_back().unwrap();
310 for (ch, span) in chars.zip(spans) {
311 tokens.append(TokenTree {
312 span: span.0,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700313 kind: TokenNode::Op(ch, Spacing::Joint),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700314 });
315 }
316
317 tokens.append(TokenTree {
318 span: span.0,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700319 kind: TokenNode::Op(ch, Spacing::Alone),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700320 });
321 }
322
323 pub fn sym(s: &str, span: &Span, tokens: &mut Tokens) {
324 tokens.append(TokenTree {
325 span: span.0,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700326 kind: TokenNode::Term(Term::intern(s)),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700327 });
328 }
329
330 pub fn delim<F>(s: &str, span: &Span, tokens: &mut Tokens, f: F)
331 where F: FnOnce(&mut Tokens)
332 {
333 tokens.append_delimited(s, span.0, f)
334 }
335}