blob: ed275efd44603c8e6f467e8783f48c5beec92e47 [file] [log] [blame]
David Tolnay18c754c2018-08-21 23:26:58 -04001//! Parsing interface for parsing a token stream into a syntax tree node.
2
3use std::cell::Cell;
4use std::fmt::Display;
5use std::marker::PhantomData;
6use std::mem;
7use std::ops::Deref;
8
David Tolnay6d67c742018-08-24 20:42:39 -04009use buffer::Cursor;
David Tolnay18c754c2018-08-21 23:26:58 -040010use proc_macro2::{Ident, Span};
David Tolnay18c754c2018-08-21 23:26:58 -040011
David Tolnay544a90f2018-08-24 20:34:03 -040012use super::error;
David Tolnay18c754c2018-08-21 23:26:58 -040013
David Tolnay544a90f2018-08-24 20:34:03 -040014pub use super::error::{Error, Result};
15pub use super::lookahead::{Lookahead1, Peek};
David Tolnay18c754c2018-08-21 23:26:58 -040016
17/// Parsing interface implemented by all types that can be parsed in a default
18/// way from a token stream.
19pub trait Parse: Sized {
20 fn parse(input: ParseStream) -> Result<Self>;
21}
22
23/// Input to a Syn parser function.
24pub type ParseStream<'a> = &'a ParseBuffer<'a>;
25
26/// Cursor position within a buffered token stream.
27#[derive(Clone)]
28pub struct ParseBuffer<'a> {
29 scope: Span,
30 cell: Cell<Cursor<'static>>,
31 marker: PhantomData<Cursor<'a>>,
32}
33
34// Not public API.
35#[doc(hidden)]
36#[derive(Copy, Clone)]
37pub struct StepCursor<'c, 'a> {
38 scope: Span,
39 cursor: Cursor<'c>,
40 marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>,
41}
42
43impl<'c, 'a> Deref for StepCursor<'c, 'a> {
44 type Target = Cursor<'c>;
45
46 fn deref(&self) -> &Self::Target {
47 &self.cursor
48 }
49}
50
51impl<'c, 'a> StepCursor<'c, 'a> {
52 // Not public API.
53 #[doc(hidden)]
54 pub fn advance(self, other: Cursor<'c>) -> Cursor<'a> {
55 unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(other) }
56 }
57
58 // Not public API.
59 #[doc(hidden)]
60 pub fn error<T: Display>(self, message: T) -> Error {
61 error::new_at(self.scope, self.cursor, message)
62 }
63}
64
65impl<'a> ParseBuffer<'a> {
66 // Not public API.
67 #[doc(hidden)]
68 pub fn new(scope: Span, cursor: Cursor<'a>) -> Self {
69 let extend = unsafe { mem::transmute::<Cursor<'a>, Cursor<'static>>(cursor) };
70 ParseBuffer {
71 scope: scope,
72 cell: Cell::new(extend),
73 marker: PhantomData,
74 }
75 }
76
77 pub fn cursor(&self) -> Cursor<'a> {
78 self.cell.get()
79 }
80
81 pub fn is_empty(&self) -> bool {
82 self.cursor().eof()
83 }
84
85 pub fn lookahead1(&self) -> Lookahead1<'a> {
86 Lookahead1::new(self.scope, self.cursor())
87 }
88
89 pub fn parse<T: Parse>(&self) -> Result<T> {
90 T::parse(self)
91 }
92
93 // Not public API.
94 #[doc(hidden)]
95 pub fn step_cursor<F, R>(&self, function: F) -> Result<R>
96 where
97 F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>,
98 {
99 match function(StepCursor {
100 scope: self.scope,
101 cursor: self.cell.get(),
102 marker: PhantomData,
103 }) {
104 Ok((ret, cursor)) => {
105 self.cell.set(cursor);
106 Ok(ret)
107 }
108 Err(err) => Err(err),
109 }
110 }
111}
112
113impl Parse for Ident {
114 fn parse(input: ParseStream) -> Result<Self> {
115 input.step_cursor(|cursor| {
116 if let Some((ident, rest)) = cursor.ident() {
David Tolnayc4fdb1a2018-08-24 21:11:07 -0400117 match ident.to_string().as_str() {
118 "_"
119 // Based on https://doc.rust-lang.org/grammar.html#keywords
120 // and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
121 | "abstract" | "as" | "become" | "box" | "break" | "const"
122 | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
123 | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
124 | "mod" | "move" | "mut" | "override" | "priv" | "proc" | "pub"
125 | "ref" | "return" | "Self" | "self" | "static" | "struct"
126 | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
127 | "virtual" | "where" | "while" | "yield" => {}
128 _ => return Ok((ident, rest)),
129 }
David Tolnay18c754c2018-08-21 23:26:58 -0400130 }
David Tolnayc4fdb1a2018-08-24 21:11:07 -0400131 Err(cursor.error("expected identifier"))
David Tolnay18c754c2018-08-21 23:26:58 -0400132 })
133 }
134}
135
136// In reality the impl would be for Punctuated.
137impl<T: Parse> Parse for Vec<T> {
138 fn parse(input: ParseStream) -> Result<Self> {
139 let mut vec = Vec::new();
140 while !input.is_empty() {
141 let t = input.parse::<T>()?;
142 vec.push(t);
143 }
144 Ok(vec)
145 }
146}