blob: 5f519a610d2bcfa2cf1b9d16a7e06603300a8f34 [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))]
Nika Layzelld73a3652017-10-24 08:57:05 -040031 #[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070032 #[derive(Default)]
33 pub struct $name(pub $($contents)*);
34
Nika Layzelld73a3652017-10-24 08:57:05 -040035 #[cfg(feature = "extra-traits")]
36 impl ::std::fmt::Debug for $name {
37 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
38 let mut t = f.debug_tuple(stringify!($name));
39 for span in &self.0 {
40 t.field(span);
41 }
42 t.finish()
43 }
44 }
45
Alex Crichton7b9e02f2017-05-30 15:54:33 -070046 #[cfg(feature = "printing")]
47 impl ::quote::ToTokens for $name {
48 fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
49 printing::op($s, &self.0, tokens);
50 }
51 }
52
53 #[cfg(feature = "parsing")]
54 impl ::Synom for $name {
Michael Layzell760fd662017-05-31 22:46:05 -040055 fn parse(tokens: $crate::Cursor) -> $crate::PResult<$name> {
Alex Crichton7b9e02f2017-05-30 15:54:33 -070056 parsing::op($s, tokens, $name)
57 }
58 }
59 }
60}
61
62macro_rules! sym {
63 (pub struct $name:ident => $s:expr) => {
64 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
65 #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
66 #[derive(Default)]
67 pub struct $name(pub Span);
68
69 #[cfg(feature = "printing")]
70 impl ::quote::ToTokens for $name {
71 fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
72 printing::sym($s, &self.0, tokens);
73 }
74 }
75
76 #[cfg(feature = "parsing")]
77 impl ::Synom for $name {
Michael Layzell760fd662017-05-31 22:46:05 -040078 fn parse(tokens: $crate::Cursor) -> $crate::PResult<$name> {
Alex Crichton7b9e02f2017-05-30 15:54:33 -070079 parsing::sym($s, tokens, $name)
80 }
81 }
82 }
83}
84
85macro_rules! delim {
86 (pub struct $name:ident => $s:expr) => {
87 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
88 #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
89 #[derive(Default)]
90 pub struct $name(pub Span);
91
92 impl $name {
93 #[cfg(feature = "printing")]
94 pub fn surround<F>(&self,
95 tokens: &mut ::quote::Tokens,
96 f: F)
97 where F: FnOnce(&mut ::quote::Tokens)
98 {
99 printing::delim($s, &self.0, tokens, f);
100 }
101
102 #[cfg(feature = "parsing")]
Michael Layzell760fd662017-05-31 22:46:05 -0400103 pub fn parse<F, R>(tokens: $crate::Cursor, f: F) -> $crate::PResult<(R, $name)>
104 where F: FnOnce($crate::Cursor) -> $crate::PResult<R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700105 {
106 parsing::delim($s, tokens, $name, f)
107 }
108 }
109 }
110}
111
112tokens! {
113 ops: {
114 (pub struct Add([Span; 1]) => "+"),
115 (pub struct AddEq([Span; 2]) => "+="),
116 (pub struct And([Span; 1]) => "&"),
117 (pub struct AndAnd([Span; 2]) => "&&"),
118 (pub struct AndEq([Span; 2]) => "&="),
119 (pub struct At([Span; 1]) => "@"),
120 (pub struct Bang([Span; 1]) => "!"),
121 (pub struct Caret([Span; 1]) => "^"),
122 (pub struct CaretEq([Span; 2]) => "^="),
123 (pub struct Colon([Span; 1]) => ":"),
124 (pub struct Colon2([Span; 2]) => "::"),
125 (pub struct Comma([Span; 1]) => ","),
126 (pub struct Div([Span; 1]) => "/"),
127 (pub struct DivEq([Span; 2]) => "/="),
128 (pub struct Dot([Span; 1]) => "."),
129 (pub struct Dot2([Span; 2]) => ".."),
130 (pub struct Dot3([Span; 3]) => "..."),
131 (pub struct Eq([Span; 1]) => "="),
132 (pub struct EqEq([Span; 2]) => "=="),
133 (pub struct Ge([Span; 2]) => ">="),
134 (pub struct Gt([Span; 1]) => ">"),
135 (pub struct Le([Span; 2]) => "<="),
136 (pub struct Lt([Span; 1]) => "<"),
137 (pub struct MulEq([Span; 2]) => "*="),
138 (pub struct Ne([Span; 2]) => "!="),
139 (pub struct Or([Span; 1]) => "|"),
140 (pub struct OrEq([Span; 2]) => "|="),
141 (pub struct OrOr([Span; 2]) => "||"),
142 (pub struct Pound([Span; 1]) => "#"),
143 (pub struct Question([Span; 1]) => "?"),
144 (pub struct RArrow([Span; 2]) => "->"),
Michael Layzellb78f3b52017-06-04 19:03:03 -0400145 (pub struct LArrow([Span; 2]) => "<-"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700146 (pub struct Rem([Span; 1]) => "%"),
147 (pub struct RemEq([Span; 2]) => "%="),
148 (pub struct Rocket([Span; 2]) => "=>"),
149 (pub struct Semi([Span; 1]) => ";"),
150 (pub struct Shl([Span; 2]) => "<<"),
151 (pub struct ShlEq([Span; 3]) => "<<="),
152 (pub struct Shr([Span; 2]) => ">>"),
153 (pub struct ShrEq([Span; 3]) => ">>="),
154 (pub struct Star([Span; 1]) => "*"),
155 (pub struct Sub([Span; 1]) => "-"),
156 (pub struct SubEq([Span; 2]) => "-="),
157 (pub struct Underscore([Span; 1]) => "_"),
158 }
159 delim: {
160 (pub struct Brace => "{"),
161 (pub struct Bracket => "["),
162 (pub struct Paren => "("),
Michael Layzell93c36282017-06-04 20:43:14 -0400163 (pub struct Group => " "),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700164 }
165 syms: {
166 (pub struct As => "as"),
Alex Crichton954046c2017-05-30 21:49:42 -0700167 (pub struct Box_ => "box"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700168 (pub struct Break => "break"),
Alex Crichton954046c2017-05-30 21:49:42 -0700169 (pub struct CapSelf => "Self"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700170 (pub struct Catch => "catch"),
171 (pub struct Const => "const"),
172 (pub struct Continue => "continue"),
173 (pub struct Crate => "crate"),
Alex Crichton954046c2017-05-30 21:49:42 -0700174 (pub struct Default_ => "default"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700175 (pub struct Do => "do"),
176 (pub struct Else => "else"),
177 (pub struct Enum => "enum"),
178 (pub struct Extern => "extern"),
Alex Crichton954046c2017-05-30 21:49:42 -0700179 (pub struct Fn_ => "fn"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700180 (pub struct For => "for"),
181 (pub struct If => "if"),
182 (pub struct Impl => "impl"),
183 (pub struct In => "in"),
184 (pub struct Let => "let"),
185 (pub struct Loop => "loop"),
186 (pub struct Match => "match"),
187 (pub struct Mod => "mod"),
188 (pub struct Move => "move"),
189 (pub struct Mut => "mut"),
190 (pub struct Pub => "pub"),
191 (pub struct Ref => "ref"),
192 (pub struct Return => "return"),
193 (pub struct Self_ => "self"),
194 (pub struct Static => "static"),
195 (pub struct Struct => "struct"),
Alex Crichton954046c2017-05-30 21:49:42 -0700196 (pub struct Super => "super"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700197 (pub struct Trait => "trait"),
198 (pub struct Type => "type"),
199 (pub struct Union => "union"),
200 (pub struct Unsafe => "unsafe"),
201 (pub struct Use => "use"),
202 (pub struct Where => "where"),
203 (pub struct While => "while"),
Alex Crichtonfe110462017-06-01 12:49:27 -0700204 (pub struct Yield => "yield"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700205 }
206}
207
208#[cfg(feature = "parsing")]
209mod parsing {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700210 use proc_macro2::{Delimiter, Spacing};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700211
Michael Layzell760fd662017-05-31 22:46:05 -0400212 use {PResult, Cursor, parse_error};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700213 use span::Span;
214
215 pub trait FromSpans: Sized {
216 fn from_spans(spans: &[Span]) -> Self;
217 }
218
219 impl FromSpans for [Span; 1] {
220 fn from_spans(spans: &[Span]) -> Self {
221 [spans[0]]
222 }
223 }
224
225 impl FromSpans for [Span; 2] {
226 fn from_spans(spans: &[Span]) -> Self {
227 [spans[0], spans[1]]
228 }
229 }
230
231 impl FromSpans for [Span; 3] {
232 fn from_spans(spans: &[Span]) -> Self {
233 [spans[0], spans[1], spans[2]]
234 }
235 }
236
237 pub fn op<'a, T, R>(s: &str,
Michael Layzell0a1a6632017-06-02 18:07:43 -0400238 mut tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700239 new: fn(T) -> R)
Michael Layzell760fd662017-05-31 22:46:05 -0400240 -> PResult<'a, R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700241 where T: FromSpans,
242 {
243 let mut spans = [Span::default(); 3];
Alex Crichton954046c2017-05-30 21:49:42 -0700244 assert!(s.len() <= spans.len());
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700245 let chars = s.chars();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700246
Alex Crichton954046c2017-05-30 21:49:42 -0700247 for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400248 match tokens.op() {
249 Some((rest, span, c, kind)) if c == ch => {
250 if i != s.len() - 1 {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700251 match kind {
252 Spacing::Joint => {}
253 _ => return parse_error(),
Michael Layzell0a1a6632017-06-02 18:07:43 -0400254 }
255 }
256 *slot = Span(span);
257 tokens = rest;
Alex Crichton954046c2017-05-30 21:49:42 -0700258 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400259 _ => return parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700260 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700261 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400262 Ok((tokens, new(T::from_spans(&spans))))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700263 }
264
265 pub fn sym<'a, T>(sym: &str,
Michael Layzell760fd662017-05-31 22:46:05 -0400266 tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700267 new: fn(Span) -> T)
Michael Layzell760fd662017-05-31 22:46:05 -0400268 -> PResult<'a, T>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700269 {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400270 if let Some((rest, span, s)) = tokens.word() {
271 if s.as_str() == sym {
272 return Ok((rest, new(Span(span))));
273 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700274 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400275 parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700276 }
277
278 pub fn delim<'a, F, R, T>(delim: &str,
Michael Layzell760fd662017-05-31 22:46:05 -0400279 tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700280 new: fn(Span) -> T,
281 f: F)
Michael Layzell760fd662017-05-31 22:46:05 -0400282 -> PResult<'a, (R, T)>
283 where F: FnOnce(Cursor) -> PResult<R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700284 {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400285 // NOTE: We should support none-delimited sequences here.
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700286 let delim = match delim {
287 "(" => Delimiter::Parenthesis,
288 "{" => Delimiter::Brace,
289 "[" => Delimiter::Bracket,
Michael Layzell93c36282017-06-04 20:43:14 -0400290 " " => Delimiter::None,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700291 _ => panic!("unknown delimiter: {}", delim),
292 };
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700293
Michael Layzell0a1a6632017-06-02 18:07:43 -0400294 if let Some(seqinfo) = tokens.seq(delim) {
295 match f(seqinfo.inside) {
296 Ok((remaining, ret)) => {
297 if remaining.eof() {
298 return Ok((seqinfo.outside, (ret, new(Span(seqinfo.span)))));
299 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700300 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400301 Err(err) => return Err(err),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700302 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700303 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400304 parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700305 }
306}
307
308#[cfg(feature = "printing")]
309mod printing {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700310 use proc_macro2::{TokenTree, TokenNode, Spacing, Term};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700311 use quote::Tokens;
312
313 use span::Span;
314
315 pub fn op(s: &str, spans: &[Span], tokens: &mut Tokens) {
316 assert_eq!(s.len(), spans.len());
317
318 let mut chars = s.chars();
319 let mut spans = spans.iter();
320 let ch = chars.next_back().unwrap();
321 let span = spans.next_back().unwrap();
322 for (ch, span) in chars.zip(spans) {
323 tokens.append(TokenTree {
324 span: span.0,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700325 kind: TokenNode::Op(ch, Spacing::Joint),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700326 });
327 }
328
329 tokens.append(TokenTree {
330 span: span.0,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700331 kind: TokenNode::Op(ch, Spacing::Alone),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700332 });
333 }
334
335 pub fn sym(s: &str, span: &Span, tokens: &mut Tokens) {
336 tokens.append(TokenTree {
337 span: span.0,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700338 kind: TokenNode::Term(Term::intern(s)),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700339 });
340 }
341
342 pub fn delim<F>(s: &str, span: &Span, tokens: &mut Tokens, f: F)
343 where F: FnOnce(&mut Tokens)
344 {
345 tokens.append_delimited(s, span.0, f)
346 }
347}