1use crate::input::Token;
4use combine::{ParseError, Parser, Stream, StreamOnce};
5use combine::error::{ConsumedResult, FastResult::*, Info, Tracked};
6use combine::stream::uncons;
7use std::marker::PhantomData;
8
9pub fn ident<I>() -> Ident<I>
11where
12 I: Stream<Item = Token>,
13 I::Error: ParseError<I::Item, I::Range, I::Position>,
14{
15 Ident(PhantomData)
16}
17
18#[derive(Copy, Clone)]
19pub struct Ident<I>(PhantomData<fn(I) -> I>)
21where
22 I: Stream<Item = Token>,
23 I::Error: ParseError<I::Item, I::Range, I::Position>;
24
25impl<I> Parser for Ident<I>
26where
27 I: Stream<Item = Token>,
28 I::Error: ParseError<I::Item, I::Range, I::Position>,
29{
30 type Input = I;
31 type Output = proc_macro2::Ident;
32 type PartialState = ();
33
34 fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
35 let position = input.position();
36 match uncons(input) {
37 EmptyOk(tok) | ConsumedOk(tok) => match tok {
38 Token::Ident(ident) => ConsumedOk(ident),
39 _ => EmptyErr(I::Error::empty(position).into()),
40 },
41 EmptyErr(err) => EmptyErr(err),
42 ConsumedErr(err) => ConsumedErr(err),
43 }
44 }
45
46 fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
47 errors.error.add_expected(Info::Borrowed("IDENT"));
48 }
49}
50
51pub fn keyword<I>(word: &'static str) -> Keyword<I>
53where
54 I: Stream<Item = Token>,
55 I::Error: ParseError<I::Item, I::Range, I::Position>,
56{
57 Keyword(word, PhantomData)
58}
59
60#[derive(Copy, Clone)]
61pub struct Keyword<I>(&'static str, PhantomData<fn(I) -> I>)
63where
64 I: Stream<Item = Token>,
65 I::Error: ParseError<I::Item, I::Range, I::Position>;
66
67impl<I> Parser for Keyword<I>
68where
69 I: Stream<Item = Token>,
70 I::Error: ParseError<I::Item, I::Range, I::Position>,
71{
72 type Input = I;
73 type Output = Token;
74 type PartialState = ();
75
76 fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
77 let position = input.position();
78 match uncons(input) {
79 EmptyOk(tok) | ConsumedOk(tok) => match tok {
80 Token::Ident(ref ident) if ident.to_string() == self.0 => ConsumedOk(tok),
81 _ => EmptyErr(I::Error::empty(position).into()),
82 },
83 EmptyErr(err) => EmptyErr(err),
84 ConsumedErr(err) => ConsumedErr(err),
85 }
86 }
87
88 fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
89 errors.error.add_expected(Info::Borrowed(self.0));
90 }
91}
92
93pub fn literal<I>() -> Literal<I>
95where
96 I: Stream<Item = Token>,
97 I::Error: ParseError<I::Item, I::Range, I::Position>,
98{
99 Literal(PhantomData)
100}
101
102#[derive(Copy, Clone)]
103pub struct Literal<I>(PhantomData<fn(I) -> I>)
105where
106 I: Stream<Item = Token>,
107 I::Error: ParseError<I::Item, I::Range, I::Position>;
108
109impl<I> Parser for Literal<I>
110where
111 I: Stream<Item = Token>,
112 I::Error: ParseError<I::Item, I::Range, I::Position>,
113{
114 type Input = I;
115 type Output = proc_macro2::Literal;
116 type PartialState = ();
117
118 fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
119 let position = input.position();
120 match uncons(input) {
121 EmptyOk(tok) | ConsumedOk(tok) => match tok {
122 Token::Literal(lit) => ConsumedOk(lit),
123 _ => EmptyErr(I::Error::empty(position).into()),
124 },
125 EmptyErr(err) => EmptyErr(err),
126 ConsumedErr(err) => ConsumedErr(err),
127 }
128 }
129
130 fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
131 errors.error.add_expected(Info::Borrowed("LITERAL"));
132 }
133}
134
135pub fn punct<I>(c: char) -> Punct<I>
140where
141 I: Stream<Item = Token>,
142 I::Error: ParseError<I::Item, I::Range, I::Position>,
143{
144 Punct(c, PhantomData)
145}
146
147#[derive(Copy, Clone)]
148pub struct Punct<I>(char, PhantomData<fn(I) -> I>)
150where
151 I: Stream<Item = Token>,
152 I::Error: ParseError<I::Item, I::Range, I::Position>;
153
154impl<I> Parser for Punct<I>
155where
156 I: Stream<Item = Token>,
157 I::Error: ParseError<I::Item, I::Range, I::Position>,
158{
159 type Input = I;
160 type Output = Token;
161 type PartialState = ();
162
163 fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
164 let position = input.position();
165 match uncons(input) {
166 EmptyOk(tok) | ConsumedOk(tok) => match tok {
167 Token::Punct(ref punct) if punct.as_char() == self.0 => ConsumedOk(tok),
168 _ => EmptyErr(I::Error::empty(position).into()),
169 },
170 EmptyErr(err) => EmptyErr(err),
171 ConsumedErr(err) => ConsumedErr(err),
172 }
173 }
174
175 fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
176 errors.error.add_expected(Info::Token(Token::Punct(proc_macro2::Punct::new(self.0, proc_macro2::Spacing::Alone))));
177 }
178}
179
180
181pub fn delim<I>(c: char) -> Delim<I>
183where
184 I: Stream<Item = Token>,
185 I::Error: ParseError<I::Item, I::Range, I::Position>,
186{
187 Delim(c, PhantomData)
188}
189
190#[derive(Copy, Clone)]
191pub struct Delim<I>(char, PhantomData<fn(I) -> I>)
193where
194 I: Stream<Item = Token>,
195 I::Error: ParseError<I::Item, I::Range, I::Position>;
196
197impl<I> Parser for Delim<I>
198where
199 I: Stream<Item = Token>,
200 I::Error: ParseError<I::Item, I::Range, I::Position>,
201{
202 type Input = I;
203 type Output = Token;
204 type PartialState = ();
205
206 fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
207 let position = input.position();
208 match uncons(input) {
209 EmptyOk(tok) | ConsumedOk(tok) => match tok {
210 Token::Delim(ch, _) if ch == self.0 => ConsumedOk(tok),
211 _ => EmptyErr(I::Error::empty(position).into()),
212 },
213 EmptyErr(err) => EmptyErr(err),
214 ConsumedErr(err) => ConsumedErr(err),
215 }
216 }
217
218 fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
219 errors.error.add_expected(Info::Token(Token::Delim(self.0, proc_macro2::Span::call_site())));
220 }
221}