blob: 52eff8e11896a034cf0c1efe5daf83464c562106 [file] [log] [blame]
David Tolnay35161ff2016-09-03 11:33:15 -07001#[macro_use]
2extern crate nom;
3
4use nom::IResult;
5use nom::multispace as space;
6
7use std::str;
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub struct Item {
11 pub ident: Ident,
12 pub vis: Visibility,
13 pub attrs: Vec<Attribute>,
14 pub generics: Generics,
15 pub body: Body,
16}
17
18pub type Ident = String;
19
20#[derive(Debug, Clone, Eq, PartialEq)]
21pub struct Attribute {
22 pub value: MetaItem,
23 pub is_sugared_doc: bool,
24}
25
26/// A compile-time attribute item.
27///
28/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
29#[derive(Debug, Clone, Eq, PartialEq)]
30pub enum MetaItem {
31 /// Word meta item.
32 ///
33 /// E.g. `test` as in `#[test]`
34 Word(Ident),
35 /// List meta item.
36 ///
37 /// E.g. `derive(..)` as in `#[derive(..)]`
38 List(Ident, Vec<MetaItem>),
39 /// Name value meta item.
40 ///
41 /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
42 NameValue(Ident, String),
43}
44
45#[derive(Debug, Clone, Eq, PartialEq, Default)]
46pub struct Generics {
47 pub lifetimes: Vec<LifetimeDef>,
48 pub ty_params: Vec<TyParam>,
49 pub where_clause: Vec<WherePredicate>,
50}
51
52/// A single predicate in a `where` clause
53#[derive(Debug, Clone, Eq, PartialEq)]
54pub enum WherePredicate {
55 /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
56 BoundPredicate(WhereBoundPredicate),
57 /// A lifetime predicate, e.g. `'a: 'b+'c`
58 RegionPredicate(WhereRegionPredicate),
59}
60
61/// A type bound.
62///
63/// E.g. `for<'c> Foo: Send+Clone+'c`
64#[derive(Debug, Clone, Eq, PartialEq)]
65pub struct WhereBoundPredicate {
66 /// Any lifetimes from a `for` binding
67 pub bound_lifetimes: Vec<LifetimeDef>,
68 /// The type being bounded
69 pub bounded_ty: Ty,
70 /// Trait and lifetime bounds (`Clone+Send+'static`)
71 pub bounds: Vec<TyParamBound>,
72}
73
74/// A lifetime predicate.
75///
76/// E.g. `'a: 'b+'c`
77#[derive(Debug, Clone, Eq, PartialEq)]
78pub struct WhereRegionPredicate {
79 pub lifetime: Lifetime,
80 pub bounds: Vec<Lifetime>,
81}
82
83#[derive(Debug, Clone, Eq, PartialEq)]
84pub struct LifetimeDef {
85 pub lifetime: Lifetime,
86 pub bounds: Vec<Lifetime>,
87}
88
89#[derive(Debug, Clone, Eq, PartialEq)]
90pub struct Lifetime {
91 pub ident: Ident,
92}
93
94#[derive(Debug, Clone, Eq, PartialEq)]
95pub struct TyParam {
96 pub ident: Ident,
97 pub bounds: Vec<TyParamBound>,
98 pub default: Option<Ty>,
99}
100
101#[derive(Debug, Clone, Eq, PartialEq)]
102pub enum TyParamBound {
103 MaybeSized,
104 Region(Lifetime),
105 Trait(PolyTraitRef),
106}
107
108#[derive(Debug, Clone, Eq, PartialEq)]
109pub struct PolyTraitRef {
110 /// The `'a` in `<'a> Foo<&'a T>`
111 pub bound_lifetimes: Vec<LifetimeDef>,
112 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
113 pub trait_ref: Path,
114}
115
116#[derive(Debug, Clone, Eq, PartialEq)]
117pub struct Path {
118 pub global: bool,
119 pub segments: Vec<PathSegment>,
120}
121
122/// A segment of a path: an identifier, an optional lifetime, and a set of types.
123///
124/// E.g. `std`, `String` or `Box<T>`
125#[derive(Debug, Clone, Eq, PartialEq)]
126pub struct PathSegment {
127 pub ident: Ident,
128 pub parameters: PathParameters,
129}
130
131impl PathSegment {
132 pub fn ident(ident: Ident) -> Self {
133 PathSegment {
134 ident: ident,
135 parameters: PathParameters::none(),
136 }
137 }
138}
139
140/// Parameters of a path segment.
141///
142/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
143#[derive(Debug, Clone, Eq, PartialEq)]
144pub enum PathParameters {
145 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
146 AngleBracketed(AngleBracketedParameterData),
147 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
148 Parenthesized(ParenthesizedParameterData),
149}
150
151impl PathParameters {
152 pub fn none() -> Self {
153 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
154 }
155}
156
157/// A path like `Foo<'a, T>`
158#[derive(Debug, Clone, Eq, PartialEq, Default)]
159pub struct AngleBracketedParameterData {
160 /// The lifetime parameters for this path segment.
161 pub lifetimes: Vec<Lifetime>,
162 /// The type parameters for this path segment, if present.
163 pub types: Vec<Ty>,
164 /// Bindings (equality constraints) on associated types, if present.
165 ///
166 /// E.g., `Foo<A=Bar>`.
167 pub bindings: Vec<TypeBinding>,
168}
169
170/// Bind a type to an associated type: `A=Foo`.
171#[derive(Debug, Clone, Eq, PartialEq)]
172pub struct TypeBinding {
173 pub ident: Ident,
174 pub ty: Ty,
175}
176
177/// A path like `Foo(A,B) -> C`
178#[derive(Debug, Clone, Eq, PartialEq)]
179pub struct ParenthesizedParameterData {
180 /// `(A, B)`
181 pub inputs: Vec<Ty>,
182 /// `C`
183 pub output: Option<Ty>,
184}
185
186#[derive(Debug, Clone, Eq, PartialEq)]
187pub enum Body {
188 Enum(Vec<Variant>),
189 Struct(Style, Vec<Field>),
190}
191
192#[derive(Debug, Clone, Eq, PartialEq)]
193pub struct Variant {
194 pub ident: Ident,
195 pub attrs: Vec<Attribute>,
196 pub style: Style,
197 pub fields: Vec<Field>,
198}
199
200#[derive(Debug, Clone, Eq, PartialEq)]
201pub enum Style {
202 Struct,
203 Tuple,
204 Unit,
205}
206
207#[derive(Debug, Clone, Eq, PartialEq)]
208pub struct Field {
209 pub ident: Option<Ident>,
210 pub vis: Visibility,
211 pub attrs: Vec<Attribute>,
212 pub ty: Ty,
213}
214
215#[derive(Debug, Clone, Eq, PartialEq)]
216pub enum Visibility {
217 Public,
218 Inherited,
219}
220
221#[derive(Debug, Clone, Eq, PartialEq)]
222pub enum Ty {
223 /// A variable-length array (`[T]`)
224 Vec(Box<Ty>),
225 /// A fixed length array (`[T; n]`)
226 FixedLengthVec(Box<Ty>, usize),
227 /// A raw pointer (`*const T` or `*mut T`)
228 Ptr(Box<MutTy>),
229 /// A reference (`&'a T` or `&'a mut T`)
230 Rptr(Option<Lifetime>, Box<MutTy>),
231 /// A bare function (e.g. `fn(usize) -> bool`)
232 BareFn(Box<BareFnTy>),
233 /// The never type (`!`)
234 Never,
235 /// A tuple (`(A, B, C, D, ...)`)
236 Tup(Vec<Ty>),
237 /// A path (`module::module::...::Type`), optionally
238 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
239 ///
240 /// Type parameters are stored in the Path itself
241 Path(Option<QSelf>, Path),
242 /// Something like `A+B`. Note that `B` must always be a path.
243 ObjectSum(Box<Ty>, Vec<TyParamBound>),
244 /// A type like `for<'a> Foo<&'a Bar>`
245 PolyTraitRef(Vec<TyParamBound>),
246 /// An `impl TraitA+TraitB` type.
247 ImplTrait(Vec<TyParamBound>),
248 /// No-op; kept solely so that we can pretty-print faithfully
249 Paren(Box<Ty>),
250 /// TyKind::Infer means the type should be inferred instead of it having been
251 /// specified. This can appear anywhere in a type.
252 Infer,
253}
254
255#[derive(Debug, Clone, Eq, PartialEq)]
256pub struct MutTy {
257 pub ty: Ty,
258 pub mutbl: Mutability,
259}
260
261#[derive(Debug, Clone, Eq, PartialEq)]
262pub enum Mutability {
263 Mutable,
264 Immutable,
265}
266
267/// The explicit Self type in a "qualified path". The actual
268/// path, including the trait and the associated item, is stored
269/// separately. `position` represents the index of the associated
270/// item qualified with this Self type.
271///
272/// ```rust,ignore
273/// <Vec<T> as a::b::Trait>::AssociatedItem
274/// ^~~~~ ~~~~~~~~~~~~~~^
275/// ty position = 3
276///
277/// <Vec<T>>::AssociatedItem
278/// ^~~~~ ^
279/// ty position = 0
280/// ```
281#[derive(Debug, Clone, Eq, PartialEq)]
282pub struct QSelf {
283 pub ty: Box<Ty>,
284 pub position: usize
285}
286
287#[derive(Debug, Clone, Eq, PartialEq)]
288pub struct BareFnTy {
289 pub lifetimes: Vec<LifetimeDef>,
290 pub decl: FnDecl
291}
292
293/// Header (not the body) of a function declaration.
294///
295/// E.g. `fn foo(bar: baz)`
296#[derive(Debug, Clone, Eq, PartialEq)]
297pub struct FnDecl {
298 pub inputs: Vec<Arg>,
299 pub output: FunctionRetTy,
300}
301
302/// An argument in a function header.
303///
304/// E.g. `bar: usize` as in `fn foo(bar: usize)`
305#[derive(Debug, Clone, Eq, PartialEq)]
306pub struct Arg {
307 pub pat: Option<Ident>,
308 pub ty: Ty,
309}
310
311#[derive(Debug, Clone, Eq, PartialEq)]
312pub enum FunctionRetTy {
313 /// Return type is not specified.
314 ///
315 /// Functions default to `()` and
316 /// closures default to inference. Span points to where return
317 /// type would be inserted.
318 Default,
319 /// Everything else
320 Ty(Ty),
321}
322
323named!(attribute<&str, Attribute>, chain!(
324 space? ~
325 tag_s!("#[") ~
326 space? ~
327 first: word ~
328 space? ~
329 tag_s!("(") ~
330 inner: separated_list!(tag_s!(", "), word) ~
331 tag_s!(")") ~
332 space? ~
333 tag_s!("]") ,
334 || { return Attribute {
335 value: MetaItem::List(first.to_string(), inner.into_iter().map(|w|
336 MetaItem::Word(w.to_string())
337 ).collect()),
338 is_sugared_doc: false,
339 } }
340));
341
342named!(visibility<&str, Visibility>,
343 map!(opt!(terminated!(tag_s!("pub"), space)), |tag| match tag {
344 Some(_) => Visibility::Public,
345 None => Visibility::Inherited,
346 })
347);
348
349fn ident_ch(ch: char) -> bool {
350 ch.is_alphanumeric() || ch == '_'
351}
352
353named!(word<&str, Ident>, map!(take_while1_s!(ident_ch), String::from));
354
355named!(path_segment<&str, PathSegment>, alt!(
356 chain!(
357 ident: word ~
358 space? ~
359 tag_s!("<") ~
360 types: many0!(ty) ~
361 space? ~
362 tag_s!(">") ,
363 || {
364 PathSegment {
365 ident: ident,
366 parameters: PathParameters::AngleBracketed(
367 AngleBracketedParameterData {
368 lifetimes: Vec::new(),
369 types: types,
370 bindings: Vec::new(),
371 }
372 ),
373 }
374 }
375 )
376 |
377 map!(word, |n| PathSegment::ident(n))
378));
379
380named!(ty<&str, Ty>, chain!(
381 global: tag_s!("::")? ~
382 segments: separated_nonempty_list!(tag_s!("::"), path_segment) ,
383 || {
384 Ty::Path(None, Path {
385 global: global.is_some(),
386 segments: segments,
387 })
388 }
389));
390
391/*
392 /// A variable-length array (`[T]`)
393 Vec(Box<Ty>),
394 /// A fixed length array (`[T; n]`)
395 FixedLengthVec(Box<Ty>, usize),
396 /// A raw pointer (`*const T` or `*mut T`)
397 Ptr(Box<MutTy>),
398 /// A reference (`&'a T` or `&'a mut T`)
399 Rptr(Option<Lifetime>, Box<MutTy>),
400 /// A bare function (e.g. `fn(usize) -> bool`)
401 BareFn(Box<BareFnTy>),
402 /// The never type (`!`)
403 Never,
404 /// A tuple (`(A, B, C, D, ...)`)
405 Tup(Vec<Ty>),
406 /// A path (`module::module::...::Type`), optionally
407 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
408 ///
409 /// Type parameters are stored in the Path itself
410 Path(Option<QSelf>, Path),
411 /// Something like `A+B`. Note that `B` must always be a path.
412 ObjectSum(Box<Ty>, Vec<TyParamBound>),
413 /// A type like `for<'a> Foo<&'a Bar>`
414 PolyTraitRef(Vec<TyParamBound>),
415 /// An `impl TraitA+TraitB` type.
416 ImplTrait(Vec<TyParamBound>),
417 /// No-op; kept solely so that we can pretty-print faithfully
418 Paren(Box<Ty>),
419 /// TyKind::Infer means the type should be inferred instead of it having been
420 /// specified. This can appear anywhere in a type.
421 Infer,
422*/
423
424named!(field<&str, Field>, chain!(
425 space? ~
426 vis: visibility ~
427 ident: word ~
428 space? ~
429 tag_s!(":") ~
430 space? ~
431 ty: ty ,
432 || {
433 Field {
434 ident: Some(ident),
435 vis: vis,
436 attrs: Vec::new(),
437 ty: ty,
438 }
439 }
440));
441
442named!(struct_body<&str, Body>, alt!(
443 chain!(
444 tag_s!("{") ~
445 fields: separated_list!(tag_s!(","), field) ~
446 space? ~
447 tag_s!(",")? ~
448 space? ~
449 tag_s!("}") ,
450 || { Body::Struct(Style::Struct, fields) }
451 )
452 |
453 chain!(
454 tag_s!("(") ~
455 separated_list!(tag_s!(","), chain!(
456 space? ~
457 vis: visibility ~
458 ty: ty ,
459 || {}
460 )) ~
461 space? ~
462 tag_s!(",")? ~
463 space? ~
464 tag_s!(")") ,
465 || { Body::Struct(Style::Tuple, Vec::new()) }
466 )
467 |
468 map!(tag_s!(";"), |_| Body::Struct(Style::Unit, Vec::new()))
469));
470
471named!(item<&str, Item>, chain!(
472 attrs: many0!(attribute) ~
473 space? ~
474 vis: visibility ~
475 tag_s!("struct") ~
476 space ~
477 ident: word ~
478 space? ~
479 body: struct_body ~
480 space? ,
481 || { return Item {
482 ident: ident,
483 vis: vis,
484 attrs: attrs,
485 generics: Generics::default(),
486 body: body,
487 } }
488));
489
490pub fn parse(input: &str) -> Result<Item, String> {
491 match item(input) {
492 IResult::Done(rest, ast) => {
493 if rest.is_empty() {
494 Ok(ast)
495 } else {
496 Err(format!("more than a single input item: {:?}", rest))
497 }
498 }
499 IResult::Error(nom::Err::Code(kind)) |
500 IResult::Error(nom::Err::Node(kind, _)) => {
501 Err(format!("failed to parse {:?}", kind))
502 }
503 IResult::Error(nom::Err::Position(kind, pos)) |
504 IResult::Error(nom::Err::NodePosition(kind, pos, _)) => {
505 Err(format!("failed to parse {:?}: {:?}", kind, pos))
506 }
507 IResult::Incomplete(_) => Err("incomplete input item".to_string()),
508 }
509}