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