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