blob: 7ddb118bc3a8eeebf5f19f0ad585ae0a3c3413e2 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnay7c3e77d2018-01-06 17:42:53 -08009//! A stably addressed token buffer supporting efficient traversal based on a
10//! cheaply copyable cursor.
Michael Layzell2a60e252017-05-31 21:36:47 -040011//!
David Tolnay7c3e77d2018-01-06 17:42:53 -080012//! The [`Synom`] trait is implemented for syntax tree types that can be parsed
13//! from one of these token cursors.
Michael Layzell2a60e252017-05-31 21:36:47 -040014//!
David Tolnay7c3e77d2018-01-06 17:42:53 -080015//! [`Synom`]: ../synom/trait.Synom.html
16//!
17//! # Example
18//!
19//! This example shows a basic token parser for parsing a token stream without
20//! using Syn's parser combinator macros.
21//!
22//! ```
23//! #![feature(proc_macro)]
24//!
25//! extern crate syn;
26//! extern crate proc_macro;
27//!
28//! #[macro_use]
29//! extern crate quote;
30//!
31//! use syn::{token, ExprTuple};
32//! use syn::buffer::{Cursor, TokenBuffer};
33//! use syn::spanned::Spanned;
34//! use syn::synom::Synom;
35//! use proc_macro::{Diagnostic, Span, TokenStream};
36//!
37//! /// A basic token parser for parsing a token stream without using Syn's
38//! /// parser combinator macros.
39//! pub struct Parser<'a> {
40//! cursor: Cursor<'a>,
41//! }
42//!
43//! impl<'a> Parser<'a> {
44//! pub fn new(cursor: Cursor<'a>) -> Self {
45//! Parser { cursor }
46//! }
47//!
48//! pub fn current_span(&self) -> Span {
49//! self.cursor.span().unstable()
50//! }
51//!
52//! pub fn parse<T: Synom>(&mut self) -> Result<T, Diagnostic> {
53//! let (val, rest) = T::parse(self.cursor)
54//! .map_err(|e| match T::description() {
55//! Some(desc) => {
56//! self.current_span().error(format!("{}: expected {}", e, desc))
57//! }
58//! None => {
59//! self.current_span().error(e.to_string())
60//! }
61//! })?;
62//!
63//! self.cursor = rest;
64//! Ok(val)
65//! }
66//!
67//! pub fn expect_eof(&mut self) -> Result<(), Diagnostic> {
68//! if !self.cursor.eof() {
69//! return Err(self.current_span().error("trailing characters; expected eof"));
70//! }
71//!
72//! Ok(())
73//! }
74//! }
75//!
76//! fn eval(input: TokenStream) -> Result<TokenStream, Diagnostic> {
77//! let buffer = TokenBuffer::new(input);
78//! let mut parser = Parser::new(buffer.begin());
79//!
80//! // Parse some syntax tree types out of the input tokens. In this case we
81//! // expect something like:
82//! //
83//! // (a, b, c) = (1, 2, 3)
84//! let a = parser.parse::<ExprTuple>()?;
85//! parser.parse::<token::Eq>()?;
86//! let b = parser.parse::<ExprTuple>()?;
87//! parser.expect_eof()?;
88//!
89//! // Perform some validation and report errors.
90//! let (a_len, b_len) = (a.elems.len(), b.elems.len());
91//! if a_len != b_len {
92//! let diag = b.span().unstable()
93//! .error(format!("expected {} element(s), got {}", a_len, b_len))
94//! .span_note(a.span().unstable(), "because of this");
95//!
96//! return Err(diag);
97//! }
98//!
99//! // Build the output tokens.
100//! let out = quote! {
101//! println!("All good! Received two tuples of size {}", #a_len);
102//! };
103//!
104//! Ok(out.into())
105//! }
106//! #
107//! # extern crate proc_macro2;
108//! #
109//! # // This method exists on proc_macro2::Span but is behind the "nightly"
110//! # // feature.
111//! # trait ToUnstableSpan {
112//! # fn unstable(&self) -> Span;
113//! # }
114//! #
115//! # impl ToUnstableSpan for proc_macro2::Span {
116//! # fn unstable(&self) -> Span {
117//! # unimplemented!()
118//! # }
119//! # }
120//! #
121//! # fn main() {}
122//! ```
Michael Layzell2a60e252017-05-31 21:36:47 -0400123
David Tolnay7c3e77d2018-01-06 17:42:53 -0800124// This module is heavily commented as it contains the only unsafe code in Syn,
125// and caution should be used when editing it. The public-facing interface is
126// 100% safe but the implementation is fragile internally.
127
128use proc_macro as pm;
129use proc_macro2::{Delimiter, Literal, Spacing, Span, Term, TokenNode, TokenStream, TokenTree};
Michael Layzell2a60e252017-05-31 21:36:47 -0400130
131use std::ptr;
Michael Layzell2a60e252017-05-31 21:36:47 -0400132use std::marker::PhantomData;
133
David Tolnayd1ec6ec2018-01-03 00:23:45 -0800134#[cfg(synom_verbose_trace)]
David Tolnayf9e1de12017-12-31 00:47:01 -0500135use std::fmt::{self, Debug};
136
David Tolnay7c3e77d2018-01-06 17:42:53 -0800137/// Internal type which is used instead of `TokenTree` to represent a token tree
138/// within a `TokenBuffer`.
Michael Layzell2a60e252017-05-31 21:36:47 -0400139enum Entry {
David Tolnay7c3e77d2018-01-06 17:42:53 -0800140 // Mimicking types from proc-macro.
David Tolnaydfc886b2018-01-06 08:03:09 -0800141 Group(Span, Delimiter, TokenBuffer),
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700142 Term(Span, Term),
143 Op(Span, char, Spacing),
Michael Layzell2a60e252017-05-31 21:36:47 -0400144 Literal(Span, Literal),
David Tolnay7c3e77d2018-01-06 17:42:53 -0800145 // End entries contain a raw pointer to the entry from the containing
146 // token tree, or null if this is the outermost level.
Michael Layzell2a60e252017-05-31 21:36:47 -0400147 End(*const Entry),
148}
149
David Tolnay7c3e77d2018-01-06 17:42:53 -0800150/// A buffer that can be efficiently traversed multiple times, unlike
151/// `TokenStream` which requires a deep copy in order to traverse more than
152/// once.
153///
154/// See the [module documentation] for an example of `TokenBuffer` in action.
155///
156/// [module documentation]: index.html
David Tolnaydfc886b2018-01-06 08:03:09 -0800157pub struct TokenBuffer {
Michael Layzell2a60e252017-05-31 21:36:47 -0400158 // NOTE: Do not derive clone on this - there are raw pointers inside which
David Tolnaydfc886b2018-01-06 08:03:09 -0800159 // will be messed up. Moving the `TokenBuffer` itself is safe as the actual
Michael Layzell2a60e252017-05-31 21:36:47 -0400160 // backing slices won't be moved.
161 data: Box<[Entry]>,
162}
163
David Tolnaydfc886b2018-01-06 08:03:09 -0800164impl TokenBuffer {
Michael Layzell2a60e252017-05-31 21:36:47 -0400165 // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
166 // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
David Tolnaydfc886b2018-01-06 08:03:09 -0800167 fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700168 // Build up the entries list, recording the locations of any Groups
Michael Layzell2a60e252017-05-31 21:36:47 -0400169 // in the list to be processed later.
170 let mut entries = Vec::new();
171 let mut seqs = Vec::new();
David Tolnay50fa4682017-12-26 23:17:22 -0500172 for tt in stream {
Michael Layzell2a60e252017-05-31 21:36:47 -0400173 match tt.kind {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700174 TokenNode::Term(sym) => {
175 entries.push(Entry::Term(tt.span, sym));
Michael Layzell2a60e252017-05-31 21:36:47 -0400176 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700177 TokenNode::Op(chr, ok) => {
Michael Layzell2a60e252017-05-31 21:36:47 -0400178 entries.push(Entry::Op(tt.span, chr, ok));
179 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700180 TokenNode::Literal(lit) => {
Michael Layzell2a60e252017-05-31 21:36:47 -0400181 entries.push(Entry::Literal(tt.span, lit));
182 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700183 TokenNode::Group(delim, seq_stream) => {
Michael Layzell2a60e252017-05-31 21:36:47 -0400184 // Record the index of the interesting entry, and store an
185 // `End(null)` there temporarially.
186 seqs.push((entries.len(), tt.span, delim, seq_stream));
187 entries.push(Entry::End(ptr::null()));
188 }
189 }
190 }
191 // Add an `End` entry to the end with a reference to the enclosing token
192 // stream which was passed in.
193 entries.push(Entry::End(up));
194
195 // NOTE: This is done to ensure that we don't accidentally modify the
196 // length of the backing buffer. The backing buffer must remain at a
197 // constant address after this point, as we are going to store a raw
198 // pointer into it.
199 let mut entries = entries.into_boxed_slice();
200 for (idx, span, delim, seq_stream) in seqs {
201 // We know that this index refers to one of the temporary
202 // `End(null)` entries, and we know that the last entry is
203 // `End(up)`, so the next index is also valid.
204 let seq_up = &entries[idx + 1] as *const Entry;
205
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700206 // The end entry stored at the end of this Entry::Group should
207 // point to the Entry which follows the Group in the list.
Michael Layzell2a60e252017-05-31 21:36:47 -0400208 let inner = Self::inner_new(seq_stream, seq_up);
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700209 entries[idx] = Entry::Group(span, delim, inner);
Michael Layzell2a60e252017-05-31 21:36:47 -0400210 }
211
David Tolnaydfc886b2018-01-06 08:03:09 -0800212 TokenBuffer { data: entries }
Michael Layzell2a60e252017-05-31 21:36:47 -0400213 }
214
David Tolnay7c3e77d2018-01-06 17:42:53 -0800215 /// Creates a `TokenBuffer` containing all the tokens from the input
216 /// `TokenStream`.
217 pub fn new(stream: pm::TokenStream) -> TokenBuffer {
218 Self::new2(stream.into())
219 }
220
221 /// Creates a `TokenBuffer` containing all the tokens from the input
222 /// `TokenStream`.
223 pub fn new2(stream: TokenStream) -> TokenBuffer {
Michael Layzell2a60e252017-05-31 21:36:47 -0400224 Self::inner_new(stream, ptr::null())
225 }
226
David Tolnay7c3e77d2018-01-06 17:42:53 -0800227 /// Creates a cursor referencing the first token in the buffer and able to
228 /// traverse until the end of the buffer.
Michael Layzell2a60e252017-05-31 21:36:47 -0400229 pub fn begin(&self) -> Cursor {
David Tolnay51382052017-12-27 13:46:21 -0500230 unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
Michael Layzell2a60e252017-05-31 21:36:47 -0400231 }
232}
233
David Tolnay7c3e77d2018-01-06 17:42:53 -0800234/// A cheaply copyable cursor into a `TokenBuffer`.
235///
236/// This cursor holds a shared reference into the immutable data which is used
237/// internally to represent a `TokenStream`, and can be efficiently manipulated
238/// and copied around.
Michael Layzell2a60e252017-05-31 21:36:47 -0400239///
David Tolnaydfc886b2018-01-06 08:03:09 -0800240/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
Michael Layzell2a60e252017-05-31 21:36:47 -0400241/// object and get a cursor to its first token with `begin()`.
242///
243/// Two cursors are equal if they have the same location in the same input
244/// stream, and have the same scope.
David Tolnay7c3e77d2018-01-06 17:42:53 -0800245///
246/// See the [module documentation] for an example of a `Cursor` in action.
247///
248/// [module documentation]: index.html
Michael Layzell2a60e252017-05-31 21:36:47 -0400249#[derive(Copy, Clone, Eq, PartialEq)]
250pub struct Cursor<'a> {
251 /// The current entry which the `Cursor` is pointing at.
252 ptr: *const Entry,
253 /// This is the only `Entry::End(..)` object which this cursor is allowed to
254 /// point at. All other `End` objects are skipped over in `Cursor::create`.
255 scope: *const Entry,
256 /// This uses the &'a reference which guarantees that these pointers are
257 /// still valid.
258 marker: PhantomData<&'a Entry>,
259}
260
Michael Layzell2a60e252017-05-31 21:36:47 -0400261impl<'a> Cursor<'a> {
David Tolnay7c3e77d2018-01-06 17:42:53 -0800262 /// Creates a cursor referencing a static empty TokenStream.
Michael Layzell2a60e252017-05-31 21:36:47 -0400263 pub fn empty() -> Self {
Michael Layzell69cf9082017-06-03 12:15:58 -0400264 // It's safe in this situation for us to put an `Entry` object in global
265 // storage, despite it not actually being safe to send across threads
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700266 // (`Term` is a reference into a thread-local table). This is because
267 // this entry never includes a `Term` object.
Michael Layzell69cf9082017-06-03 12:15:58 -0400268 //
269 // This wrapper struct allows us to break the rules and put a `Sync`
270 // object in global storage.
271 struct UnsafeSyncEntry(Entry);
272 unsafe impl Sync for UnsafeSyncEntry {}
David Tolnay51382052017-12-27 13:46:21 -0500273 static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));
Michael Layzell69cf9082017-06-03 12:15:58 -0400274
Michael Layzell2a60e252017-05-31 21:36:47 -0400275 Cursor {
Michael Layzell69cf9082017-06-03 12:15:58 -0400276 ptr: &EMPTY_ENTRY.0,
277 scope: &EMPTY_ENTRY.0,
Michael Layzell2a60e252017-05-31 21:36:47 -0400278 marker: PhantomData,
279 }
280 }
281
282 /// This create method intelligently exits non-explicitly-entered
283 /// `None`-delimited scopes when the cursor reaches the end of them,
284 /// allowing for them to be treated transparently.
285 unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
286 // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
287 // past it, unless `ptr == scope`, which means that we're at the edge of
288 // our cursor's scope. We should only have `ptr != scope` at the exit
David Tolnayc10676a2017-12-27 23:42:36 -0500289 // from None-delimited groups entered with `ignore_none`.
Michael Layzell2a60e252017-05-31 21:36:47 -0400290 while let Entry::End(exit) = *ptr {
291 if ptr == scope {
292 break;
293 }
294 ptr = exit;
295 }
296
297 Cursor {
298 ptr: ptr,
299 scope: scope,
300 marker: PhantomData,
301 }
302 }
303
304 /// Get the current entry.
305 fn entry(self) -> &'a Entry {
306 unsafe { &*self.ptr }
307 }
308
309 /// Bump the cursor to point at the next token after the current one. This
310 /// is undefined behavior if the cursor is currently looking at an
311 /// `Entry::End`.
312 unsafe fn bump(self) -> Cursor<'a> {
313 Cursor::create(self.ptr.offset(1), self.scope)
314 }
315
David Tolnayc10676a2017-12-27 23:42:36 -0500316 /// If the cursor is looking at a `None`-delimited group, move it to look at
317 /// the first token inside instead. If the group is empty, this will move
318 /// the cursor past the `None`-delimited group.
Michael Layzell2a60e252017-05-31 21:36:47 -0400319 ///
320 /// WARNING: This mutates its argument.
321 fn ignore_none(&mut self) {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700322 if let Entry::Group(_, Delimiter::None, ref buf) = *self.entry() {
Michael Layzell2a60e252017-05-31 21:36:47 -0400323 // NOTE: We call `Cursor::create` here to make sure that situations
324 // where we should immediately exit the span after entering it are
325 // handled correctly.
326 unsafe {
327 *self = Cursor::create(&buf.data[0], self.scope);
328 }
329 }
330 }
331
David Tolnay7c3e77d2018-01-06 17:42:53 -0800332 /// Checks whether the cursor is currently pointing at the end of its valid
333 /// scope.
Michael Layzell2a60e252017-05-31 21:36:47 -0400334 #[inline]
335 pub fn eof(self) -> bool {
336 // We're at eof if we're at the end of our scope.
337 self.ptr == self.scope
338 }
339
David Tolnay7c3e77d2018-01-06 17:42:53 -0800340 /// If the cursor is pointing at a `Group` with the given delimiter, returns
341 /// a cursor into that group and one pointing to the next `TokenTree`.
David Tolnay65729482017-12-31 16:14:50 -0500342 pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
David Tolnayc10676a2017-12-27 23:42:36 -0500343 // If we're not trying to enter a none-delimited group, we want to
Michael Layzell2a60e252017-05-31 21:36:47 -0400344 // ignore them. We have to make sure to _not_ ignore them when we want
345 // to enter them, of course. For obvious reasons.
David Tolnayc10676a2017-12-27 23:42:36 -0500346 if delim != Delimiter::None {
Michael Layzell2a60e252017-05-31 21:36:47 -0400347 self.ignore_none();
348 }
349
David Tolnayc10676a2017-12-27 23:42:36 -0500350 if let Entry::Group(span, group_delim, ref buf) = *self.entry() {
351 if group_delim == delim {
David Tolnay65729482017-12-31 16:14:50 -0500352 return Some((buf.begin(), span, unsafe { self.bump() }));
Michael Layzell2a60e252017-05-31 21:36:47 -0400353 }
Michael Layzell2a60e252017-05-31 21:36:47 -0400354 }
David Tolnayc10676a2017-12-27 23:42:36 -0500355
356 None
Michael Layzell2a60e252017-05-31 21:36:47 -0400357 }
358
David Tolnay7c3e77d2018-01-06 17:42:53 -0800359 /// If the cursor is pointing at a `Term`, returns it along with a cursor
360 /// pointing at the next `TokenTree`.
David Tolnay65729482017-12-31 16:14:50 -0500361 pub fn term(mut self) -> Option<(Span, Term, Cursor<'a>)> {
Michael Layzell2a60e252017-05-31 21:36:47 -0400362 self.ignore_none();
363 match *self.entry() {
David Tolnay65729482017-12-31 16:14:50 -0500364 Entry::Term(span, term) => Some((span, term, unsafe { self.bump() })),
David Tolnay51382052017-12-27 13:46:21 -0500365 _ => None,
Michael Layzell2a60e252017-05-31 21:36:47 -0400366 }
367 }
368
David Tolnay7c3e77d2018-01-06 17:42:53 -0800369 /// If the cursor is pointing at an `Op`, returns it along with a cursor
370 /// pointing at the next `TokenTree`.
David Tolnay65729482017-12-31 16:14:50 -0500371 pub fn op(mut self) -> Option<(Span, char, Spacing, Cursor<'a>)> {
Michael Layzell2a60e252017-05-31 21:36:47 -0400372 self.ignore_none();
373 match *self.entry() {
David Tolnay65729482017-12-31 16:14:50 -0500374 Entry::Op(span, op, spacing) => Some((span, op, spacing, unsafe { self.bump() })),
David Tolnay51382052017-12-27 13:46:21 -0500375 _ => None,
Michael Layzell2a60e252017-05-31 21:36:47 -0400376 }
377 }
378
David Tolnay7c3e77d2018-01-06 17:42:53 -0800379 /// If the cursor is pointing at a `Literal`, return it along with a cursor
380 /// pointing at the next `TokenTree`.
David Tolnay65729482017-12-31 16:14:50 -0500381 pub fn literal(mut self) -> Option<(Span, Literal, Cursor<'a>)> {
Michael Layzell2a60e252017-05-31 21:36:47 -0400382 self.ignore_none();
383 match *self.entry() {
David Tolnay65729482017-12-31 16:14:50 -0500384 Entry::Literal(span, ref lit) => Some((span, lit.clone(), unsafe { self.bump() })),
David Tolnay51382052017-12-27 13:46:21 -0500385 _ => None,
Michael Layzell2a60e252017-05-31 21:36:47 -0400386 }
387 }
388
David Tolnay7c3e77d2018-01-06 17:42:53 -0800389 /// Copies all remaining tokens visible from this cursor into a
390 /// `TokenStream`.
Michael Layzell2a60e252017-05-31 21:36:47 -0400391 pub fn token_stream(self) -> TokenStream {
392 let mut tts = Vec::new();
393 let mut cursor = self;
David Tolnay65729482017-12-31 16:14:50 -0500394 while let Some((tt, rest)) = cursor.token_tree() {
Michael Layzell2a60e252017-05-31 21:36:47 -0400395 tts.push(tt);
David Tolnay65729482017-12-31 16:14:50 -0500396 cursor = rest;
Michael Layzell2a60e252017-05-31 21:36:47 -0400397 }
398 tts.into_iter().collect()
399 }
400
David Tolnay7c3e77d2018-01-06 17:42:53 -0800401 /// If the cursor is pointing at a `TokenTree`, returns it along with a
402 /// cursor pointing at the next `TokenTree`.
Michael Layzell2a60e252017-05-31 21:36:47 -0400403 ///
David Tolnay7c3e77d2018-01-06 17:42:53 -0800404 /// Returns `None` if the cursor has reached the end of its stream.
405 ///
406 /// This method does not treat `None`-delimited groups as transparent, and
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700407 /// will return a `Group(None, ..)` if the cursor is looking at one.
David Tolnay65729482017-12-31 16:14:50 -0500408 pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
Michael Layzell2a60e252017-05-31 21:36:47 -0400409 let tree = match *self.entry() {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700410 Entry::Group(span, delim, ref buf) => {
Michael Layzell2a60e252017-05-31 21:36:47 -0400411 let stream = buf.begin().token_stream();
412 TokenTree {
413 span: span,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700414 kind: TokenNode::Group(delim, stream),
Michael Layzell2a60e252017-05-31 21:36:47 -0400415 }
416 }
David Tolnay51382052017-12-27 13:46:21 -0500417 Entry::Literal(span, ref lit) => TokenTree {
418 span: span,
419 kind: TokenNode::Literal(lit.clone()),
420 },
421 Entry::Term(span, sym) => TokenTree {
422 span: span,
423 kind: TokenNode::Term(sym),
424 },
David Tolnay73c98de2017-12-31 15:56:56 -0500425 Entry::Op(span, chr, spacing) => TokenTree {
David Tolnay51382052017-12-27 13:46:21 -0500426 span: span,
David Tolnay73c98de2017-12-31 15:56:56 -0500427 kind: TokenNode::Op(chr, spacing),
David Tolnay51382052017-12-27 13:46:21 -0500428 },
Michael Layzell2a60e252017-05-31 21:36:47 -0400429 Entry::End(..) => {
430 return None;
431 }
432 };
433
David Tolnay65729482017-12-31 16:14:50 -0500434 Some((tree, unsafe { self.bump() }))
Michael Layzell2a60e252017-05-31 21:36:47 -0400435 }
David Tolnay225efa22017-12-31 16:51:29 -0500436
437 /// Returns the `Span` of the current token, or `Span::call_site()` if this
438 /// cursor points to eof.
439 pub fn span(self) -> Span {
440 match *self.entry() {
David Tolnay76ebcdd2018-01-05 17:07:26 -0800441 Entry::Group(span, ..)
442 | Entry::Literal(span, ..)
443 | Entry::Term(span, ..)
444 | Entry::Op(span, ..) => span,
David Tolnay225efa22017-12-31 16:51:29 -0500445 Entry::End(..) => Span::call_site(),
446 }
447 }
Michael Layzell2a60e252017-05-31 21:36:47 -0400448}
449
450// We do a custom implementation for `Debug` as the default implementation is
451// pretty useless.
David Tolnayd1ec6ec2018-01-03 00:23:45 -0800452#[cfg(synom_verbose_trace)]
David Tolnayf9e1de12017-12-31 00:47:01 -0500453impl<'a> Debug for Cursor<'a> {
Michael Layzell2a60e252017-05-31 21:36:47 -0400454 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Nika Layzellae81b372017-12-05 14:12:33 -0500455 // Print what the cursor is currently looking at.
456 // This will look like Cursor("some remaining tokens here")
457 f.debug_tuple("Cursor")
458 .field(&self.token_stream().to_string())
Michael Layzell2a60e252017-05-31 21:36:47 -0400459 .finish()
460 }
461}