cpp_syn-0.12.0/Cargo.toml01006440000765000002400000002734130566610510013425 0ustar0000000000000000# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "cpp_syn" version = "0.12.0" authors = ["Michael Layzell ", "David Tolnay "] include = ["Cargo.toml", "src/**/*.rs"] description = "Internal rust-cpp nom parser for Rust source code" documentation = "https://docs.rs/cpp_syn" license = "MIT/Apache-2.0" repository = "https://github.com/mystor/cpp_syn" [dependencies.clippy] version = "0.*" optional = true [dependencies.cpp_synom] version = "0.12.0" optional = true [dependencies.quote] version = "0.3" optional = true [dependencies.unicode-xid] version = "0.0.4" optional = true [dev-dependencies.syntex_pos] version = "0.52" [dev-dependencies.syntex_syntax] version = "0.52" [dev-dependencies.tempdir] version = "0.3.5" [dev-dependencies.time] version = "0.1.35" [dev-dependencies.walkdir] version = "1.0.1" [features] aster = [] default = ["parsing", "printing"] fold = [] full = [] parsing = ["unicode-xid", "cpp_synom"] printing = ["quote"] visit = [] cpp_syn-0.12.0/Cargo.toml.orig01006440000765000002400000001625130566610510014362 0ustar0000000000000000[package] name = "cpp_syn" version = "0.12.0" # don't forget to update version in readme for breaking changes authors = ["Michael Layzell ", "David Tolnay "] license = "MIT/Apache-2.0" description = "Internal rust-cpp nom parser for Rust source code" repository = "https://github.com/mystor/cpp_syn" documentation = "https://docs.rs/cpp_syn" include = ["Cargo.toml", "src/**/*.rs"] [features] default = ["parsing", "printing"] aster = [] full = [] parsing = ["unicode-xid", "cpp_synom"] printing = ["quote"] visit = [] fold = [] [dependencies] clippy = { version = "0.*", optional = true } quote = { version = "0.3", optional = true } unicode-xid = { version = "0.0.4", optional = true } cpp_synom = { version = "0.12.0", path = "synom", optional = true } [dev-dependencies] syntex_pos = "0.52" syntex_syntax = "0.52" tempdir = "0.3.5" time = "0.1.35" walkdir = "1.0.1" cpp_syn-0.12.0/src/aster/generics.rs01006440000765000002400000013600130412351710015533 0ustar0000000000000000use {Generics, Ident, LifetimeDef, TyParam, WhereClause, WherePredicate}; use aster::invoke::{Identity, Invoke}; use aster::lifetime::{IntoLifetime, LifetimeDefBuilder, IntoLifetimeDef}; use aster::path::IntoPath; use aster::ty_param::TyParamBuilder; use aster::where_predicate::WherePredicateBuilder; pub struct GenericsBuilder { callback: F, lifetimes: Vec, ty_params: Vec, predicates: Vec, } impl GenericsBuilder { pub fn new() -> Self { GenericsBuilder::with_callback(Identity) } pub fn from_generics(generics: Generics) -> Self { GenericsBuilder::from_generics_with_callback(generics, Identity) } } impl GenericsBuilder where F: Invoke { pub fn with_callback(callback: F) -> Self { GenericsBuilder { callback: callback, lifetimes: Vec::new(), ty_params: Vec::new(), predicates: Vec::new(), } } pub fn from_generics_with_callback(generics: Generics, callback: F) -> Self { GenericsBuilder { callback: callback, lifetimes: generics.lifetimes, ty_params: generics.ty_params, predicates: generics.where_clause.predicates, } } pub fn with(self, generics: Generics) -> Self { self.with_lifetimes(generics.lifetimes.into_iter()) .with_ty_params(generics.ty_params.into_iter()) .with_predicates(generics.where_clause.predicates.into_iter()) } pub fn with_lifetimes(mut self, iter: I) -> Self where I: IntoIterator, L: IntoLifetimeDef { let iter = iter.into_iter().map(|lifetime_def| lifetime_def.into_lifetime_def()); self.lifetimes.extend(iter); self } pub fn with_lifetime_names(mut self, iter: I) -> Self where I: IntoIterator, N: Into { for name in iter { self = self.lifetime_name(name); } self } pub fn with_lifetime(mut self, lifetime: LifetimeDef) -> Self { self.lifetimes.push(lifetime); self } pub fn lifetime_name(self, name: N) -> Self where N: Into { self.lifetime(name).build() } pub fn lifetime(self, name: N) -> LifetimeDefBuilder where N: Into { LifetimeDefBuilder::with_callback(name, self) } pub fn with_ty_params(mut self, iter: I) -> Self where I: IntoIterator { self.ty_params.extend(iter); self } pub fn with_ty_param_ids(mut self, iter: I) -> Self where I: IntoIterator, T: Into { for id in iter { self = self.ty_param_id(id); } self } pub fn with_ty_param(mut self, ty_param: TyParam) -> Self { self.ty_params.push(ty_param); self } pub fn ty_param_id(self, id: I) -> Self where I: Into { self.ty_param(id).build() } pub fn ty_param(self, id: I) -> TyParamBuilder where I: Into { TyParamBuilder::with_callback(id, self) } pub fn with_predicates(mut self, iter: I) -> Self where I: IntoIterator { self.predicates.extend(iter); self } pub fn with_predicate(mut self, predicate: WherePredicate) -> Self { self.predicates.push(predicate); self } pub fn predicate(self) -> WherePredicateBuilder { WherePredicateBuilder::with_callback(self) } pub fn add_lifetime_bound(mut self, lifetime: L) -> Self where L: IntoLifetime { let lifetime = lifetime.into_lifetime(); for lifetime_def in &mut self.lifetimes { lifetime_def.bounds.push(lifetime.clone()); } for ty_param in &mut self.ty_params { *ty_param = TyParamBuilder::from_ty_param(ty_param.clone()) .lifetime_bound(lifetime.clone()) .build(); } self } pub fn add_ty_param_bound

(mut self, path: P) -> Self where P: IntoPath { let path = path.into_path(); for ty_param in &mut self.ty_params { *ty_param = TyParamBuilder::from_ty_param(ty_param.clone()) .trait_bound(path.clone()) .build() .build(); } self } pub fn strip_bounds(self) -> Self { self.strip_lifetimes() .strip_ty_params() .strip_predicates() } pub fn strip_lifetimes(mut self) -> Self { for lifetime in &mut self.lifetimes { lifetime.bounds = vec![]; } self } pub fn strip_ty_params(mut self) -> Self { for ty_param in &mut self.ty_params { ty_param.bounds = vec![]; } self } pub fn strip_predicates(mut self) -> Self { self.predicates = vec![]; self } pub fn build(self) -> F::Result { self.callback.invoke(Generics { lifetimes: self.lifetimes, ty_params: self.ty_params, where_clause: WhereClause { predicates: self.predicates }, }) } } impl Invoke for GenericsBuilder where F: Invoke { type Result = Self; fn invoke(self, lifetime: LifetimeDef) -> Self { self.with_lifetime(lifetime) } } impl Invoke for GenericsBuilder where F: Invoke { type Result = Self; fn invoke(self, ty_param: TyParam) -> Self { self.with_ty_param(ty_param) } } impl Invoke for GenericsBuilder where F: Invoke { type Result = Self; fn invoke(self, predicate: WherePredicate) -> Self { self.with_predicate(predicate) } } cpp_syn-0.12.0/src/aster/ident.rs01006440000765000002400000001133130412351710015035 0ustar0000000000000000use Ident; pub trait ToIdent { fn to_ident(&self) -> Ident; } impl ToIdent for Ident { fn to_ident(&self) -> Ident { self.clone() } } impl<'a> ToIdent for &'a str { fn to_ident(&self) -> Ident { (**self).into() } } impl ToIdent for String { fn to_ident(&self) -> Ident { self.clone().into() } } impl<'a, T> ToIdent for &'a T where T: ToIdent { fn to_ident(&self) -> Ident { (**self).to_ident() } } impl<'a, T> ToIdent for &'a mut T where T: ToIdent { fn to_ident(&self) -> Ident { (**self).to_ident() } } cpp_syn-0.12.0/src/aster/invoke.rs01006440000765000002400000000363130412351710015231 0ustar0000000000000000pub trait Invoke { type Result; fn invoke(self, arg: A) -> Self::Result; } #[derive(Copy, Clone)] pub struct Identity; impl Invoke for Identity { type Result = A; fn invoke(self, arg: A) -> A { arg } } cpp_syn-0.12.0/src/aster/lifetime.rs01006440000765000002400000004421130412351710015533 0ustar0000000000000000use {Ident, Lifetime, LifetimeDef}; use aster::invoke::{Invoke, Identity}; // //////////////////////////////////////////////////////////////////////////// pub trait IntoLifetime { fn into_lifetime(self) -> Lifetime; } impl IntoLifetime for Lifetime { fn into_lifetime(self) -> Lifetime { self } } impl<'a> IntoLifetime for &'a str { fn into_lifetime(self) -> Lifetime { Lifetime { ident: self.into() } } } // //////////////////////////////////////////////////////////////////////////// pub trait IntoLifetimeDef { fn into_lifetime_def(self) -> LifetimeDef; } impl IntoLifetimeDef for LifetimeDef { fn into_lifetime_def(self) -> LifetimeDef { self } } impl IntoLifetimeDef for Lifetime { fn into_lifetime_def(self) -> LifetimeDef { LifetimeDef { attrs: vec![], lifetime: self, bounds: vec![], } } } impl<'a> IntoLifetimeDef for &'a str { fn into_lifetime_def(self) -> LifetimeDef { self.into_lifetime().into_lifetime_def() } } impl IntoLifetimeDef for String { fn into_lifetime_def(self) -> LifetimeDef { (*self).into_lifetime().into_lifetime_def() } } // //////////////////////////////////////////////////////////////////////////// pub struct LifetimeDefBuilder { callback: F, lifetime: Lifetime, bounds: Vec, } impl LifetimeDefBuilder { pub fn new(name: N) -> Self where N: Into { LifetimeDefBuilder::with_callback(name, Identity) } } impl LifetimeDefBuilder where F: Invoke { pub fn with_callback(name: N, callback: F) -> Self where N: Into { let lifetime = Lifetime { ident: name.into() }; LifetimeDefBuilder { callback: callback, lifetime: lifetime, bounds: Vec::new(), } } pub fn bound(mut self, name: N) -> Self where N: Into { let lifetime = Lifetime { ident: name.into() }; self.bounds.push(lifetime); self } pub fn build(self) -> F::Result { self.callback.invoke(LifetimeDef { attrs: vec![], lifetime: self.lifetime, bounds: self.bounds, }) } } cpp_syn-0.12.0/src/aster/mod.rs01006440000765000002400000001153127753264210014527 0ustar0000000000000000use super::*; pub mod generics; pub mod ident; pub mod invoke; pub mod lifetime; pub mod path; pub mod qpath; pub mod ty; pub mod ty_param; pub mod where_predicate; pub fn id(id: I) -> Ident where I: Into { id.into() } pub fn from_generics(generics: Generics) -> generics::GenericsBuilder { generics::GenericsBuilder::from_generics(generics) } pub fn where_predicate() -> where_predicate::WherePredicateBuilder { where_predicate::WherePredicateBuilder::new() } pub fn ty() -> ty::TyBuilder { ty::TyBuilder::new() } pub fn path() -> path::PathBuilder { path::PathBuilder::new() } cpp_syn-0.12.0/src/aster/path.rs01006440000765000002400000017366130412351710014705 0ustar0000000000000000use {AngleBracketedParameterData, Generics, Ident, Lifetime, ParenthesizedParameterData, Path, PathParameters, PathSegment, Ty, TypeBinding}; use aster::ident::ToIdent; use aster::invoke::{Invoke, Identity}; use aster::lifetime::IntoLifetime; use aster::ty::TyBuilder; // //////////////////////////////////////////////////////////////////////////// pub trait IntoPath { fn into_path(self) -> Path; } impl IntoPath for Path { fn into_path(self) -> Path { self } } impl IntoPath for Ident { fn into_path(self) -> Path { PathBuilder::new().id(self).build() } } impl<'a> IntoPath for &'a str { fn into_path(self) -> Path { PathBuilder::new().id(self).build() } } impl IntoPath for String { fn into_path(self) -> Path { (&*self).into_path() } } impl<'a, T> IntoPath for &'a [T] where T: ToIdent { fn into_path(self) -> Path { PathBuilder::new().ids(self).build() } } // //////////////////////////////////////////////////////////////////////////// pub struct PathBuilder { callback: F, global: bool, } impl PathBuilder { pub fn new() -> Self { PathBuilder::with_callback(Identity) } } impl PathBuilder where F: Invoke { pub fn with_callback(callback: F) -> Self { PathBuilder { callback: callback, global: false, } } pub fn build(self, path: Path) -> F::Result { self.callback.invoke(path) } pub fn global(mut self) -> Self { self.global = true; self } pub fn ids(self, ids: I) -> PathSegmentsBuilder where I: IntoIterator, T: ToIdent { let mut ids = ids.into_iter(); let id = ids.next().expect("passed path with no id"); self.id(id).ids(ids) } pub fn id(self, id: I) -> PathSegmentsBuilder where I: ToIdent { self.segment(id).build() } pub fn segment(self, id: I) -> PathSegmentBuilder> where I: ToIdent { PathSegmentBuilder::with_callback(id, PathSegmentsBuilder { callback: self.callback, global: self.global, segments: Vec::new(), }) } } // //////////////////////////////////////////////////////////////////////////// pub struct PathSegmentsBuilder { callback: F, global: bool, segments: Vec, } impl PathSegmentsBuilder where F: Invoke { pub fn ids(mut self, ids: I) -> PathSegmentsBuilder where I: IntoIterator, T: ToIdent { for id in ids { self = self.id(id); } self } pub fn id(self, id: T) -> PathSegmentsBuilder where T: ToIdent { self.segment(id).build() } pub fn segment(self, id: T) -> PathSegmentBuilder where T: ToIdent { PathSegmentBuilder::with_callback(id, self) } pub fn build(self) -> F::Result { self.callback.invoke(Path { global: self.global, segments: self.segments, }) } } impl Invoke for PathSegmentsBuilder { type Result = Self; fn invoke(mut self, segment: PathSegment) -> Self { self.segments.push(segment); self } } // //////////////////////////////////////////////////////////////////////////// pub struct PathSegmentBuilder { callback: F, id: Ident, lifetimes: Vec, tys: Vec, bindings: Vec, } impl PathSegmentBuilder where F: Invoke { pub fn with_callback(id: I, callback: F) -> Self where I: ToIdent { PathSegmentBuilder { callback: callback, id: id.to_ident(), lifetimes: Vec::new(), tys: Vec::new(), bindings: Vec::new(), } } pub fn with_generics(self, generics: Generics) -> Self { // Strip off the bounds. let lifetimes = generics.lifetimes .iter() .map(|lifetime_def| lifetime_def.lifetime.clone()); let tys = generics.ty_params .iter() .map(|ty_param| TyBuilder::new().id(ty_param.ident.clone())); self.with_lifetimes(lifetimes) .with_tys(tys) } pub fn with_lifetimes(mut self, iter: I) -> Self where I: IntoIterator, L: IntoLifetime { let iter = iter.into_iter().map(|lifetime| lifetime.into_lifetime()); self.lifetimes.extend(iter); self } pub fn with_lifetime(mut self, lifetime: L) -> Self where L: IntoLifetime { self.lifetimes.push(lifetime.into_lifetime()); self } pub fn lifetime(self, name: N) -> Self where N: ToIdent { let lifetime = Lifetime { ident: name.to_ident() }; self.with_lifetime(lifetime) } pub fn with_tys(mut self, iter: I) -> Self where I: IntoIterator { self.tys.extend(iter); self } pub fn with_ty(mut self, ty: Ty) -> Self { self.tys.push(ty); self } pub fn ty(self) -> TyBuilder { TyBuilder::with_callback(self) } pub fn with_binding(mut self, binding: TypeBinding) -> Self { self.bindings.push(binding); self } pub fn binding(self, id: T) -> TyBuilder> where T: ToIdent { TyBuilder::with_callback(TypeBindingBuilder { id: id.to_ident(), builder: self, }) } pub fn no_return(self) -> F::Result { self.build_return(None) } pub fn return_(self) -> TyBuilder> { TyBuilder::with_callback(PathSegmentReturnBuilder(self)) } pub fn build_return(self, output: Option) -> F::Result { let data = ParenthesizedParameterData { inputs: self.tys, output: output, }; let parameters = PathParameters::Parenthesized(data); self.callback.invoke(PathSegment { ident: self.id, parameters: parameters, }) } pub fn build(self) -> F::Result { let data = AngleBracketedParameterData { lifetimes: self.lifetimes, types: self.tys, bindings: self.bindings, }; let parameters = PathParameters::AngleBracketed(data); self.callback.invoke(PathSegment { ident: self.id, parameters: parameters, }) } } impl Invoke for PathSegmentBuilder where F: Invoke { type Result = Self; fn invoke(self, ty: Ty) -> Self { self.with_ty(ty) } } // //////////////////////////////////////////////////////////////////////////// pub struct TypeBindingBuilder { id: Ident, builder: PathSegmentBuilder, } impl Invoke for TypeBindingBuilder where F: Invoke { type Result = PathSegmentBuilder; fn invoke(self, ty: Ty) -> Self::Result { let id = self.id; self.builder.with_binding(TypeBinding { ident: id, ty: ty, }) } } // //////////////////////////////////////////////////////////////////////////// pub struct PathSegmentReturnBuilder(PathSegmentBuilder); impl Invoke for PathSegmentReturnBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> Self::Result { self.0.build_return(Some(ty)) } } cpp_syn-0.12.0/src/aster/qpath.rs01006440000765000002400000007117130412351710015057 0ustar0000000000000000use {Path, PathSegment, QSelf, Ty}; use aster::ident::ToIdent; use aster::invoke::{Invoke, Identity}; use aster::path::{PathBuilder, PathSegmentBuilder}; use aster::ty::TyBuilder; // //////////////////////////////////////////////////////////////////////////// pub struct QPathBuilder { callback: F, } impl QPathBuilder { pub fn new() -> Self { QPathBuilder::with_callback(Identity) } } impl QPathBuilder where F: Invoke<(QSelf, Path)> { /// Construct a `QPathBuilder` that will call the `callback` with a constructed `QSelf` /// and `Path`. pub fn with_callback(callback: F) -> Self { QPathBuilder { callback: callback } } /// Build a qualified path first by starting with a type builder. pub fn with_ty(self, ty: Ty) -> QPathTyBuilder { QPathTyBuilder { builder: self, ty: ty, } } /// Build a qualified path first by starting with a type builder. pub fn ty(self) -> TyBuilder { TyBuilder::with_callback(self) } /// Build a qualified path with a concrete type and path. pub fn build(self, qself: QSelf, path: Path) -> F::Result { self.callback.invoke((qself, path)) } } impl Invoke for QPathBuilder where F: Invoke<(QSelf, Path)> { type Result = QPathTyBuilder; fn invoke(self, ty: Ty) -> QPathTyBuilder { self.with_ty(ty) } } // //////////////////////////////////////////////////////////////////////////// pub struct QPathTyBuilder { builder: QPathBuilder, ty: Ty, } impl QPathTyBuilder where F: Invoke<(QSelf, Path)> { /// Build a qualified path with a path builder. // Clippy false positive // https://github.com/Manishearth/rust-clippy/issues/1285 #[cfg_attr(feature = "clippy", allow(wrong_self_convention))] pub fn as_(self) -> PathBuilder { PathBuilder::with_callback(self) } pub fn id(self, id: T) -> F::Result where T: ToIdent { let path = Path { global: false, segments: vec![], }; self.as_().build(path).id(id) } pub fn segment(self, id: T) -> PathSegmentBuilder> where T: ToIdent { let path = Path { global: false, segments: vec![], }; self.as_().build(path).segment(id) } } impl Invoke for QPathTyBuilder where F: Invoke<(QSelf, Path)> { type Result = QPathQSelfBuilder; fn invoke(self, path: Path) -> QPathQSelfBuilder { QPathQSelfBuilder { builder: self.builder, qself: QSelf { ty: Box::new(self.ty), position: path.segments.len(), }, path: path, } } } // //////////////////////////////////////////////////////////////////////////// pub struct QPathQSelfBuilder { builder: QPathBuilder, qself: QSelf, path: Path, } impl QPathQSelfBuilder where F: Invoke<(QSelf, Path)> { pub fn id(self, id: T) -> F::Result where T: ToIdent { self.segment(id).build() } pub fn segment(self, id: T) -> PathSegmentBuilder> where T: ToIdent { PathSegmentBuilder::with_callback(id, self) } } impl Invoke for QPathQSelfBuilder where F: Invoke<(QSelf, Path)> { type Result = F::Result; fn invoke(mut self, segment: PathSegment) -> F::Result { self.path.segments.push(segment); self.builder.build(self.qself, self.path) } } cpp_syn-0.12.0/src/aster/ty.rs01006440000765000002400000025416130415266210014403 0ustar0000000000000000use {Generics, Lifetime, MutTy, Mutability, Path, QSelf, Ty, TyParamBound}; use aster::ident::ToIdent; use aster::invoke::{Invoke, Identity}; use aster::lifetime::IntoLifetime; use aster::path::PathBuilder; use aster::qpath::QPathBuilder; use aster::ty_param::TyParamBoundBuilder; // //////////////////////////////////////////////////////////////////////////// pub struct TyBuilder { callback: F, } impl TyBuilder { pub fn new() -> Self { TyBuilder::with_callback(Identity) } } impl TyBuilder where F: Invoke { pub fn with_callback(callback: F) -> Self { TyBuilder { callback: callback } } pub fn build(self, ty: Ty) -> F::Result { self.callback.invoke(ty) } pub fn id(self, id: I) -> F::Result where I: ToIdent { self.path().id(id).build() } pub fn build_path(self, path: Path) -> F::Result { self.build(Ty::Path(None, path)) } pub fn build_qpath(self, qself: QSelf, path: Path) -> F::Result { self.build(Ty::Path(Some(qself), path)) } pub fn path(self) -> PathBuilder> { PathBuilder::with_callback(TyPathBuilder(self)) } pub fn qpath(self) -> QPathBuilder> { QPathBuilder::with_callback(TyQPathBuilder(self)) } pub fn isize(self) -> F::Result { self.id("isize") } pub fn i8(self) -> F::Result { self.id("i8") } pub fn i16(self) -> F::Result { self.id("i16") } pub fn i32(self) -> F::Result { self.id("i32") } pub fn i64(self) -> F::Result { self.id("i64") } pub fn usize(self) -> F::Result { self.id("usize") } pub fn u8(self) -> F::Result { self.id("u8") } pub fn u16(self) -> F::Result { self.id("u16") } pub fn u32(self) -> F::Result { self.id("u32") } pub fn u64(self) -> F::Result { self.id("u64") } pub fn f32(self) -> F::Result { self.id("f32") } pub fn f64(self) -> F::Result { self.id("f64") } pub fn bool(self) -> F::Result { self.id("bool") } pub fn unit(self) -> F::Result { self.tuple().build() } pub fn tuple(self) -> TyTupleBuilder { TyTupleBuilder { builder: self, tys: vec![], } } pub fn build_slice(self, ty: Ty) -> F::Result { self.build(Ty::Slice(Box::new(ty))) } pub fn slice(self) -> TyBuilder> { TyBuilder::with_callback(TySliceBuilder(self)) } pub fn ref_(self) -> TyRefBuilder { TyRefBuilder { builder: self, lifetime: None, mutability: Mutability::Immutable, } } pub fn never(self) -> F::Result { self.build(Ty::Never) } pub fn infer(self) -> F::Result { self.build(Ty::Infer) } pub fn option(self) -> TyBuilder> { TyBuilder::with_callback(TyOptionBuilder(self)) } pub fn result(self) -> TyBuilder> { TyBuilder::with_callback(TyResultOkBuilder(self)) } pub fn phantom_data(self) -> TyBuilder> { TyBuilder::with_callback(TyPhantomDataBuilder(self)) } pub fn box_(self) -> TyBuilder> { TyBuilder::with_callback(TyBoxBuilder(self)) } pub fn iterator(self) -> TyBuilder> { TyBuilder::with_callback(TyIteratorBuilder(self)) } pub fn impl_trait(self) -> TyImplTraitTyBuilder { TyImplTraitTyBuilder { builder: self, bounds: Vec::new(), } } } // //////////////////////////////////////////////////////////////////////////// pub struct TyPathBuilder(TyBuilder); impl Invoke for TyPathBuilder where F: Invoke { type Result = F::Result; fn invoke(self, path: Path) -> F::Result { self.0.build_path(path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyQPathBuilder(TyBuilder); impl Invoke<(QSelf, Path)> for TyQPathBuilder where F: Invoke { type Result = F::Result; fn invoke(self, (qself, path): (QSelf, Path)) -> F::Result { self.0.build_qpath(qself, path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TySliceBuilder(TyBuilder); impl Invoke for TySliceBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { self.0.build_slice(ty) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyRefBuilder { builder: TyBuilder, lifetime: Option, mutability: Mutability, } impl TyRefBuilder where F: Invoke { pub fn mut_(mut self) -> Self { self.mutability = Mutability::Mutable; self } pub fn lifetime(mut self, name: N) -> Self where N: ToIdent { self.lifetime = Some(Lifetime { ident: name.to_ident() }); self } pub fn build_ty(self, ty: Ty) -> F::Result { let ty = MutTy { ty: ty, mutability: self.mutability, }; self.builder.build(Ty::Rptr(self.lifetime, Box::new(ty))) } pub fn ty(self) -> TyBuilder { TyBuilder::with_callback(self) } } impl Invoke for TyRefBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { self.build_ty(ty) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyOptionBuilder(TyBuilder); impl Invoke for TyOptionBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { let path = PathBuilder::new() .global() .id("std") .id("option") .segment("Option") .with_ty(ty) .build() .build(); self.0.build_path(path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyResultOkBuilder(TyBuilder); impl Invoke for TyResultOkBuilder where F: Invoke { type Result = TyBuilder>; fn invoke(self, ty: Ty) -> TyBuilder> { TyBuilder::with_callback(TyResultErrBuilder(self.0, ty)) } } pub struct TyResultErrBuilder(TyBuilder, Ty); impl Invoke for TyResultErrBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { let path = PathBuilder::new() .global() .id("std") .id("result") .segment("Result") .with_ty(self.1) .with_ty(ty) .build() .build(); self.0.build_path(path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyPhantomDataBuilder(TyBuilder); impl Invoke for TyPhantomDataBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { let path = PathBuilder::new() .global() .id("std") .id("marker") .segment("PhantomData") .with_ty(ty) .build() .build(); self.0.build_path(path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyBoxBuilder(TyBuilder); impl Invoke for TyBoxBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { let path = PathBuilder::new() .global() .id("std") .id("boxed") .segment("Box") .with_ty(ty) .build() .build(); self.0.build_path(path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyIteratorBuilder(TyBuilder); impl Invoke for TyIteratorBuilder where F: Invoke { type Result = F::Result; fn invoke(self, ty: Ty) -> F::Result { let path = PathBuilder::new() .global() .id("std") .id("iter") .segment("Iterator") .binding("Item") .build(ty.clone()) .build() .build(); self.0.build_path(path) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyImplTraitTyBuilder { builder: TyBuilder, bounds: Vec, } impl TyImplTraitTyBuilder where F: Invoke { pub fn with_bounds(mut self, iter: I) -> Self where I: Iterator { self.bounds.extend(iter); self } pub fn with_bound(mut self, bound: TyParamBound) -> Self { self.bounds.push(bound); self } pub fn bound(self) -> TyParamBoundBuilder { TyParamBoundBuilder::with_callback(self) } pub fn with_generics(self, generics: Generics) -> Self { self.with_lifetimes(generics.lifetimes .into_iter() .map(|def| def.lifetime)) } pub fn with_lifetimes(mut self, lifetimes: I) -> Self where I: Iterator, L: IntoLifetime { for lifetime in lifetimes { self = self.lifetime(lifetime); } self } pub fn lifetime(self, lifetime: L) -> Self where L: IntoLifetime { self.bound().lifetime(lifetime) } pub fn build(self) -> F::Result { let bounds = self.bounds; self.builder.build(Ty::ImplTrait(bounds)) } } impl Invoke for TyImplTraitTyBuilder where F: Invoke { type Result = Self; fn invoke(self, bound: TyParamBound) -> Self { self.with_bound(bound) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyTupleBuilder { builder: TyBuilder, tys: Vec, } impl TyTupleBuilder where F: Invoke { pub fn with_tys(mut self, iter: I) -> Self where I: IntoIterator { self.tys.extend(iter); self } pub fn with_ty(mut self, ty: Ty) -> Self { self.tys.push(ty); self } pub fn ty(self) -> TyBuilder { TyBuilder::with_callback(self) } pub fn build(self) -> F::Result { self.builder.build(Ty::Tup(self.tys)) } } impl Invoke for TyTupleBuilder where F: Invoke { type Result = Self; fn invoke(self, ty: Ty) -> Self { self.with_ty(ty) } } cpp_syn-0.12.0/src/aster/ty_param.rs01006440000765000002400000015004130412351710015550 0ustar0000000000000000use {Ident, LifetimeDef, Path, PolyTraitRef, TraitBoundModifier, Ty, TyParam, TyParamBound}; use aster::invoke::{Invoke, Identity}; use aster::lifetime::{IntoLifetime, IntoLifetimeDef, LifetimeDefBuilder}; use aster::path::{IntoPath, PathBuilder}; use aster::ty::TyBuilder; // //////////////////////////////////////////////////////////////////////////// pub struct TyParamBuilder { callback: F, id: Ident, bounds: Vec, default: Option, } impl TyParamBuilder { pub fn new(id: I) -> Self where I: Into { TyParamBuilder::with_callback(id, Identity) } pub fn from_ty_param(ty_param: TyParam) -> Self { TyParamBuilder::from_ty_param_with_callback(Identity, ty_param) } } impl TyParamBuilder where F: Invoke { pub fn with_callback(id: I, callback: F) -> Self where I: Into { TyParamBuilder { callback: callback, id: id.into(), bounds: Vec::new(), default: None, } } pub fn from_ty_param_with_callback(callback: F, ty_param: TyParam) -> Self { TyParamBuilder { callback: callback, id: ty_param.ident, bounds: ty_param.bounds, default: ty_param.default, } } pub fn with_default(mut self, ty: Ty) -> Self { self.default = Some(ty); self } pub fn default(self) -> TyBuilder { TyBuilder::with_callback(self) } pub fn with_bound(mut self, bound: TyParamBound) -> Self { self.bounds.push(bound); self } pub fn bound(self) -> TyParamBoundBuilder { TyParamBoundBuilder::with_callback(self) } pub fn with_trait_bound(self, trait_ref: PolyTraitRef) -> Self { self.bound().build_trait(trait_ref, TraitBoundModifier::None) } pub fn trait_bound

(self, path: P) -> PolyTraitRefBuilder where P: IntoPath { PolyTraitRefBuilder::with_callback(path, self) } pub fn lifetime_bound(mut self, lifetime: L) -> Self where L: IntoLifetime { let lifetime = lifetime.into_lifetime(); self.bounds.push(TyParamBound::Region(lifetime)); self } pub fn build(self) -> F::Result { self.callback.invoke(TyParam { attrs: vec![], ident: self.id, bounds: self.bounds, default: self.default, }) } } impl Invoke for TyParamBuilder where F: Invoke { type Result = Self; fn invoke(self, ty: Ty) -> Self { self.with_default(ty) } } impl Invoke for TyParamBuilder where F: Invoke { type Result = Self; fn invoke(self, bound: TyParamBound) -> Self { self.with_bound(bound) } } impl Invoke for TyParamBuilder where F: Invoke { type Result = Self; fn invoke(self, trait_ref: PolyTraitRef) -> Self { self.with_trait_bound(trait_ref) } } // //////////////////////////////////////////////////////////////////////////// pub struct TyParamBoundBuilder { callback: F, } impl TyParamBoundBuilder { pub fn new() -> Self { TyParamBoundBuilder::with_callback(Identity) } } impl TyParamBoundBuilder where F: Invoke { pub fn with_callback(callback: F) -> Self { TyParamBoundBuilder { callback: callback } } pub fn build_trait(self, poly_trait: PolyTraitRef, modifier: TraitBoundModifier) -> F::Result { let bound = TyParamBound::Trait(poly_trait, modifier); self.callback.invoke(bound) } pub fn trait_

(self, path: P) -> PolyTraitRefBuilder> where P: IntoPath { let builder = TraitTyParamBoundBuilder { builder: self, modifier: TraitBoundModifier::None, }; PolyTraitRefBuilder::with_callback(path, builder) } pub fn maybe_trait

(self, path: P) -> PolyTraitRefBuilder> where P: IntoPath { let builder = TraitTyParamBoundBuilder { builder: self, modifier: TraitBoundModifier::Maybe, }; PolyTraitRefBuilder::with_callback(path, builder) } pub fn iterator(self, ty: Ty) -> PolyTraitRefBuilder> { let path = PathBuilder::new() .global() .id("std") .id("iter") .segment("Iterator") .binding("Item") .build(ty) .build() .build(); self.trait_(path) } pub fn lifetime(self, lifetime: L) -> F::Result where L: IntoLifetime { let lifetime = lifetime.into_lifetime(); self.callback.invoke(TyParamBound::Region(lifetime)) } } // //////////////////////////////////////////////////////////////////////////// pub struct TraitTyParamBoundBuilder { builder: TyParamBoundBuilder, modifier: TraitBoundModifier, } impl Invoke for TraitTyParamBoundBuilder where F: Invoke { type Result = F::Result; fn invoke(self, poly_trait: PolyTraitRef) -> Self::Result { self.builder.build_trait(poly_trait, self.modifier) } } // //////////////////////////////////////////////////////////////////////////// pub struct PolyTraitRefBuilder { callback: F, trait_ref: Path, lifetimes: Vec, } impl PolyTraitRefBuilder where F: Invoke { pub fn with_callback

(path: P, callback: F) -> Self where P: IntoPath { PolyTraitRefBuilder { callback: callback, trait_ref: path.into_path(), lifetimes: Vec::new(), } } pub fn with_lifetime(mut self, lifetime: L) -> Self where L: IntoLifetimeDef { self.lifetimes.push(lifetime.into_lifetime_def()); self } pub fn lifetime(self, name: N) -> LifetimeDefBuilder where N: Into { LifetimeDefBuilder::with_callback(name, self) } pub fn build(self) -> F::Result { self.callback.invoke(PolyTraitRef { bound_lifetimes: self.lifetimes, trait_ref: self.trait_ref, }) } } impl Invoke for PolyTraitRefBuilder where F: Invoke { type Result = Self; fn invoke(self, lifetime: LifetimeDef) -> Self { self.with_lifetime(lifetime) } } cpp_syn-0.12.0/src/aster/where_predicate.rs01006440000765000002400000015252130412351710017073 0ustar0000000000000000use {Ident, Lifetime, LifetimeDef, Ty, TyParamBound, WhereBoundPredicate, WherePredicate, WhereRegionPredicate}; use aster::invoke::{Invoke, Identity}; use aster::lifetime::{IntoLifetime, IntoLifetimeDef, LifetimeDefBuilder}; use aster::path::IntoPath; use aster::ty::TyBuilder; use aster::ty_param::{TyParamBoundBuilder, PolyTraitRefBuilder, TraitTyParamBoundBuilder}; // //////////////////////////////////////////////////////////////////////////// pub struct WherePredicateBuilder { callback: F, } impl WherePredicateBuilder { pub fn new() -> Self { WherePredicateBuilder::with_callback(Identity) } } impl WherePredicateBuilder where F: Invoke { pub fn with_callback(callback: F) -> Self { WherePredicateBuilder { callback: callback } } pub fn bound(self) -> TyBuilder { TyBuilder::with_callback(self) } pub fn lifetime(self, lifetime: L) -> WhereRegionPredicateBuilder where L: IntoLifetime { WhereRegionPredicateBuilder { callback: self.callback, lifetime: lifetime.into_lifetime(), bounds: Vec::new(), } } } impl Invoke for WherePredicateBuilder where F: Invoke { type Result = WhereBoundPredicateTyBuilder; fn invoke(self, ty: Ty) -> Self::Result { WhereBoundPredicateTyBuilder { callback: self.callback, ty: ty, bound_lifetimes: Vec::new(), } } } // //////////////////////////////////////////////////////////////////////////// pub struct WhereBoundPredicateBuilder { callback: F, } impl Invoke for WhereBoundPredicateBuilder where F: Invoke { type Result = WhereBoundPredicateTyBuilder; fn invoke(self, ty: Ty) -> Self::Result { WhereBoundPredicateTyBuilder { callback: self.callback, ty: ty, bound_lifetimes: Vec::new(), } } } // //////////////////////////////////////////////////////////////////////////// pub struct WhereBoundPredicateTyBuilder { callback: F, ty: Ty, bound_lifetimes: Vec, } impl WhereBoundPredicateTyBuilder where F: Invoke { pub fn with_for_lifetime(mut self, lifetime: L) -> Self where L: IntoLifetimeDef { self.bound_lifetimes.push(lifetime.into_lifetime_def()); self } pub fn for_lifetime(self, name: N) -> LifetimeDefBuilder where N: Into { LifetimeDefBuilder::with_callback(name, self) } pub fn with_bound(self, bound: TyParamBound) -> WhereBoundPredicateTyBoundsBuilder { WhereBoundPredicateTyBoundsBuilder { callback: self.callback, ty: self.ty, bound_lifetimes: self.bound_lifetimes, bounds: vec![bound], } } pub fn bound(self) -> TyParamBoundBuilder> { let builder = WhereBoundPredicateTyBoundsBuilder { callback: self.callback, ty: self.ty, bound_lifetimes: self.bound_lifetimes, bounds: vec![], }; TyParamBoundBuilder::with_callback(builder) } pub fn trait_

(self, path: P) -> PolyTraitRefBuilder>> where P: IntoPath { self.bound().trait_(path) } pub fn lifetime(self, lifetime: L) -> WhereBoundPredicateTyBoundsBuilder where L: IntoLifetime { self.bound().lifetime(lifetime) } } impl Invoke for WhereBoundPredicateTyBuilder where F: Invoke { type Result = Self; fn invoke(self, lifetime: LifetimeDef) -> Self { self.with_for_lifetime(lifetime) } } impl Invoke for WhereBoundPredicateTyBuilder where F: Invoke { type Result = WhereBoundPredicateTyBoundsBuilder; fn invoke(self, bound: TyParamBound) -> Self::Result { self.with_bound(bound) } } // //////////////////////////////////////////////////////////////////////////// pub struct WhereBoundPredicateTyBoundsBuilder { callback: F, ty: Ty, bound_lifetimes: Vec, bounds: Vec, } impl WhereBoundPredicateTyBoundsBuilder where F: Invoke { pub fn with_for_lifetime(mut self, lifetime: L) -> Self where L: IntoLifetimeDef { self.bound_lifetimes.push(lifetime.into_lifetime_def()); self } pub fn for_lifetime(self, name: N) -> LifetimeDefBuilder where N: Into { LifetimeDefBuilder::with_callback(name, self) } pub fn with_bound(mut self, bound: TyParamBound) -> Self { self.bounds.push(bound); self } pub fn bound(self) -> TyParamBoundBuilder { TyParamBoundBuilder::with_callback(self) } pub fn trait_

(self, path: P) -> PolyTraitRefBuilder> where P: IntoPath { self.bound().trait_(path) } pub fn lifetime(self, lifetime: L) -> Self where L: IntoLifetime { self.bound().lifetime(lifetime) } pub fn build(self) -> F::Result { let predicate = WhereBoundPredicate { bound_lifetimes: self.bound_lifetimes, bounded_ty: self.ty, bounds: self.bounds, }; self.callback.invoke(WherePredicate::BoundPredicate(predicate)) } } impl Invoke for WhereBoundPredicateTyBoundsBuilder where F: Invoke { type Result = Self; fn invoke(self, lifetime: LifetimeDef) -> Self { self.with_for_lifetime(lifetime) } } impl Invoke for WhereBoundPredicateTyBoundsBuilder where F: Invoke { type Result = Self; fn invoke(self, bound: TyParamBound) -> Self { self.with_bound(bound) } } // //////////////////////////////////////////////////////////////////////////// pub struct WhereRegionPredicateBuilder { callback: F, lifetime: Lifetime, bounds: Vec, } impl WhereRegionPredicateBuilder where F: Invoke { pub fn bound(mut self, lifetime: L) -> Self where L: IntoLifetime { self.bounds.push(lifetime.into_lifetime()); self } pub fn build(self) -> F::Result { let predicate = WhereRegionPredicate { lifetime: self.lifetime, bounds: self.bounds, }; self.callback.invoke(WherePredicate::RegionPredicate(predicate)) } } cpp_syn-0.12.0/src/attr.rs01006440000765000002400000021613130566610420013601 0ustar0000000000000000use super::*; use std::iter; /// Doc-comments are promoted to attributes that have `is_sugared_doc` = true #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Attribute { pub style: AttrStyle, pub value: MetaItem, pub is_sugared_doc: bool, pub span: Span, } impl Attribute { pub fn name(&self) -> &str { self.value.name() } } /// Distinguishes between Attributes that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum AttrStyle { Outer, Inner, } /// A compile-time attribute item. /// /// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum MetaItem { /// Word meta item. /// /// E.g. `test` as in `#[test]` Word(Ident), /// List meta item. /// /// E.g. `derive(..)` as in `#[derive(..)]` List(Ident, Vec), /// Name value meta item. /// /// E.g. `feature = "foo"` as in `#[feature = "foo"]` NameValue(Ident, Lit), } impl MetaItem { pub fn name(&self) -> &str { match *self { MetaItem::Word(ref name) | MetaItem::List(ref name, _) | MetaItem::NameValue(ref name, _) => name.as_ref(), } } } /// Possible values inside of compile-time attribute lists. /// /// E.g. the '..' in `#[name(..)]`. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum NestedMetaItem { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), /// A literal. /// /// E.g. "foo", 64, true Literal(Lit), } pub trait FilterAttrs<'a> { type Ret: Iterator; fn outer(self) -> Self::Ret; fn inner(self) -> Self::Ret; } impl<'a, T> FilterAttrs<'a> for T where T: IntoIterator { type Ret = iter::Filter bool>; fn outer(self) -> Self::Ret { fn is_outer(attr: &&Attribute) -> bool { attr.style == AttrStyle::Outer } self.into_iter().filter(is_outer) } fn inner(self) -> Self::Ret { fn is_inner(attr: &&Attribute) -> bool { attr.style == AttrStyle::Inner } self.into_iter().filter(is_inner) } } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use ident::parsing::ident; use lit::parsing::lit; use synom::space::{block_comment, whitespace}; #[cfg(feature = "full")] named!(pub inner_attr -> Attribute, add_span!(alt!( do_parse!( punct!("#") >> punct!("!") >> punct!("[") >> meta_item: meta_item >> punct!("]") >> (Attribute { style: AttrStyle::Inner, value: meta_item, is_sugared_doc: false, span: DUMMY_SPAN, }) ) | do_parse!( punct!("//!") >> content: spanned!(take_until!("\n")) >> (Attribute { style: AttrStyle::Inner, value: MetaItem::NameValue( "doc".into(), Lit { span: Span { lo: content.span.lo - 3, // include the '//!' hi: content.span.hi, }, .. format!("//!{}", content.node).into() } ), is_sugared_doc: true, span: DUMMY_SPAN, }) ) | do_parse!( option!(whitespace) >> peek!(tag!("/*!")) >> com: spanned!(block_comment) >> (Attribute { style: AttrStyle::Inner, value: MetaItem::NameValue( "doc".into(), com.into(), ), is_sugared_doc: true, span: DUMMY_SPAN, }) ) ))); named!(pub outer_attr -> Attribute, add_span!(alt!( do_parse!( punct!("#") >> punct!("[") >> meta_item: meta_item >> punct!("]") >> (Attribute { style: AttrStyle::Outer, value: meta_item, is_sugared_doc: false, span: DUMMY_SPAN, }) ) | do_parse!( punct!("///") >> not!(tag!("/")) >> content: spanned!(take_until!("\n")) >> (Attribute { style: AttrStyle::Outer, value: MetaItem::NameValue( "doc".into(), Lit { span: Span { lo: content.span.lo - 3, // Include the '///' hi: content.span.hi, }, .. format!("///{}", content.node).into() }, ), is_sugared_doc: true, span: DUMMY_SPAN, }) ) | do_parse!( option!(whitespace) >> peek!(tuple!(tag!("/**"), not!(tag!("*")))) >> com: spanned!(block_comment) >> (Attribute { style: AttrStyle::Outer, value: MetaItem::NameValue( "doc".into(), com.into(), ), is_sugared_doc: true, span: DUMMY_SPAN, }) ) ))); named!(meta_item -> MetaItem, alt!( do_parse!( id: ident >> punct!("(") >> inner: terminated_list!(punct!(","), nested_meta_item) >> punct!(")") >> (MetaItem::List(id, inner)) ) | do_parse!( name: ident >> punct!("=") >> value: lit >> (MetaItem::NameValue(name, value)) ) | map!(ident, MetaItem::Word) )); named!(nested_meta_item -> NestedMetaItem, alt!( meta_item => { NestedMetaItem::MetaItem } | lit => { NestedMetaItem::Literal } )); } #[cfg(feature = "printing")] mod printing { use super::*; use lit::{Lit, LitKind, StrStyle}; use quote::{Tokens, ToTokens}; impl ToTokens for Attribute { fn to_tokens(&self, tokens: &mut Tokens) { if let Attribute { style, value: MetaItem::NameValue(ref name, Lit { node: LitKind::Str(ref value, StrStyle::Cooked), .. }), is_sugared_doc: true, .. } = *self { if name == "doc" { match style { AttrStyle::Inner if value.starts_with("//!") => { tokens.append(&format!("{}\n", value)); return; } AttrStyle::Inner if value.starts_with("/*!") => { tokens.append(value); return; } AttrStyle::Outer if value.starts_with("///") => { tokens.append(&format!("{}\n", value)); return; } AttrStyle::Outer if value.starts_with("/**") => { tokens.append(value); return; } _ => {} } } } tokens.append("#"); if let AttrStyle::Inner = self.style { tokens.append("!"); } tokens.append("["); self.value.to_tokens(tokens); tokens.append("]"); } } impl ToTokens for MetaItem { fn to_tokens(&self, tokens: &mut Tokens) { match *self { MetaItem::Word(ref ident) => { ident.to_tokens(tokens); } MetaItem::List(ref ident, ref inner) => { ident.to_tokens(tokens); tokens.append("("); tokens.append_separated(inner, ","); tokens.append(")"); } MetaItem::NameValue(ref name, ref value) => { name.to_tokens(tokens); tokens.append("="); value.to_tokens(tokens); } } } } impl ToTokens for NestedMetaItem { fn to_tokens(&self, tokens: &mut Tokens) { match *self { NestedMetaItem::MetaItem(ref nested) => { nested.to_tokens(tokens); } NestedMetaItem::Literal(ref lit) => { lit.to_tokens(tokens); } } } } } cpp_syn-0.12.0/src/constant.rs01006440000765000002400000011564130412351710014456 0ustar0000000000000000use super::*; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ConstExpr { /// A function call /// /// The first field resolves to the function itself, /// and the second field is the list of arguments Call(Box, Vec), /// A binary operation (For example: `a + b`, `a * b`) Binary(BinOp, Box, Box), /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, Box), /// A literal (For example: `1`, `"foo"`) Lit(Lit), /// A cast (`foo as f64`) Cast(Box, Box), /// Variable reference, possibly containing `::` and/or type /// parameters, e.g. foo::bar::. Path(Path), /// An indexing operation (`foo[2]`) Index(Box, Box), /// No-op: used solely so we can pretty-print faithfully Paren(Box), /// If compiling with full support for expression syntax, any expression is /// allowed Other(Other), } #[cfg(not(feature = "full"))] #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Other { _private: (), } #[cfg(feature = "full")] pub type Other = Expr; #[cfg(feature = "parsing")] pub mod parsing { use super::*; use {BinOp, Ty}; use lit::parsing::lit; use op::parsing::{binop, unop}; use ty::parsing::{path, ty}; named!(pub const_expr -> ConstExpr, do_parse!( mut e: alt!( expr_unary | expr_lit | expr_path | expr_paren ) >> many0!(alt!( tap!(args: and_call => { e = ConstExpr::Call(Box::new(e), args); }) | tap!(more: and_binary => { let (op, other) = more; e = ConstExpr::Binary(op, Box::new(e), Box::new(other)); }) | tap!(ty: and_cast => { e = ConstExpr::Cast(Box::new(e), Box::new(ty)); }) | tap!(i: and_index => { e = ConstExpr::Index(Box::new(e), Box::new(i)); }) )) >> (e) )); named!(and_call -> Vec, do_parse!( punct!("(") >> args: terminated_list!(punct!(","), const_expr) >> punct!(")") >> (args) )); named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr)); named!(expr_unary -> ConstExpr, do_parse!( operator: unop >> operand: const_expr >> (ConstExpr::Unary(operator, Box::new(operand))) )); named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit)); named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path)); named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]"))); named!(expr_paren -> ConstExpr, do_parse!( punct!("(") >> e: const_expr >> punct!(")") >> (ConstExpr::Paren(Box::new(e))) )); named!(and_cast -> Ty, do_parse!( keyword!("as") >> ty: ty >> (ty) )); } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for ConstExpr { fn to_tokens(&self, tokens: &mut Tokens) { match *self { ConstExpr::Call(ref func, ref args) => { func.to_tokens(tokens); tokens.append("("); tokens.append_separated(args, ","); tokens.append(")"); } ConstExpr::Binary(op, ref left, ref right) => { left.to_tokens(tokens); op.to_tokens(tokens); right.to_tokens(tokens); } ConstExpr::Unary(op, ref expr) => { op.to_tokens(tokens); expr.to_tokens(tokens); } ConstExpr::Lit(ref lit) => lit.to_tokens(tokens), ConstExpr::Cast(ref expr, ref ty) => { expr.to_tokens(tokens); tokens.append("as"); ty.to_tokens(tokens); } ConstExpr::Path(ref path) => path.to_tokens(tokens), ConstExpr::Index(ref expr, ref index) => { expr.to_tokens(tokens); tokens.append("["); index.to_tokens(tokens); tokens.append("]"); } ConstExpr::Paren(ref expr) => { tokens.append("("); expr.to_tokens(tokens); tokens.append(")"); } ConstExpr::Other(ref other) => { other.to_tokens(tokens); } } } } #[cfg(not(feature = "full"))] impl ToTokens for Other { fn to_tokens(&self, _tokens: &mut Tokens) { unreachable!() } } } cpp_syn-0.12.0/src/data.rs01006440000765000002400000014511130412351710013531 0ustar0000000000000000use super::*; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Variant { pub ident: Ident, pub attrs: Vec, pub data: VariantData, /// Explicit discriminant, e.g. `Foo = 1` pub discriminant: Option, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum VariantData { Struct(Vec), Tuple(Vec), Unit, } impl VariantData { pub fn fields(&self) -> &[Field] { match *self { VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, VariantData::Unit => &[], } } pub fn fields_mut(&mut self) -> &mut [Field] { match *self { VariantData::Struct(ref mut fields) | VariantData::Tuple(ref mut fields) => fields, VariantData::Unit => &mut [], } } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Field { pub ident: Option, pub vis: Visibility, pub attrs: Vec, pub ty: Ty, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Visibility { Public, Crate, Restricted(Box), Inherited, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use WhereClause; use attr::parsing::outer_attr; use constant::parsing::const_expr; use generics::parsing::where_clause; use ident::parsing::ident; use ty::parsing::{path, ty}; named!(pub struct_body -> (WhereClause, VariantData), alt!( do_parse!( wh: where_clause >> body: struct_like_body >> (wh, VariantData::Struct(body)) ) | do_parse!( body: tuple_like_body >> wh: where_clause >> punct!(";") >> (wh, VariantData::Tuple(body)) ) | do_parse!( wh: where_clause >> punct!(";") >> (wh, VariantData::Unit) ) )); named!(pub enum_body -> (WhereClause, Vec), do_parse!( wh: where_clause >> punct!("{") >> variants: terminated_list!(punct!(","), variant) >> punct!("}") >> (wh, variants) )); named!(variant -> Variant, do_parse!( attrs: many0!(outer_attr) >> id: ident >> data: alt!( struct_like_body => { VariantData::Struct } | tuple_like_body => { VariantData::Tuple } | epsilon!() => { |_| VariantData::Unit } ) >> disr: option!(preceded!(punct!("="), const_expr)) >> (Variant { ident: id, attrs: attrs, data: data, discriminant: disr, }) )); named!(pub struct_like_body -> Vec, do_parse!( punct!("{") >> fields: terminated_list!(punct!(","), struct_field) >> punct!("}") >> (fields) )); named!(tuple_like_body -> Vec, do_parse!( punct!("(") >> fields: terminated_list!(punct!(","), tuple_field) >> punct!(")") >> (fields) )); named!(struct_field -> Field, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> id: ident >> punct!(":") >> ty: ty >> (Field { ident: Some(id), vis: vis, attrs: attrs, ty: ty, }) )); named!(tuple_field -> Field, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> ty: ty >> (Field { ident: None, vis: vis, attrs: attrs, ty: ty, }) )); named!(pub visibility -> Visibility, alt!( do_parse!( keyword!("pub") >> punct!("(") >> keyword!("crate") >> punct!(")") >> (Visibility::Crate) ) | do_parse!( keyword!("pub") >> punct!("(") >> restricted: path >> punct!(")") >> (Visibility::Restricted(Box::new(restricted))) ) | keyword!("pub") => { |_| Visibility::Public } | epsilon!() => { |_| Visibility::Inherited } )); } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for Variant { fn to_tokens(&self, tokens: &mut Tokens) { for attr in &self.attrs { attr.to_tokens(tokens); } self.ident.to_tokens(tokens); self.data.to_tokens(tokens); if let Some(ref disr) = self.discriminant { tokens.append("="); disr.to_tokens(tokens); } } } impl ToTokens for VariantData { fn to_tokens(&self, tokens: &mut Tokens) { match *self { VariantData::Struct(ref fields) => { tokens.append("{"); tokens.append_separated(fields, ","); tokens.append("}"); } VariantData::Tuple(ref fields) => { tokens.append("("); tokens.append_separated(fields, ","); tokens.append(")"); } VariantData::Unit => {} } } } impl ToTokens for Field { fn to_tokens(&self, tokens: &mut Tokens) { for attr in &self.attrs { attr.to_tokens(tokens); } self.vis.to_tokens(tokens); if let Some(ref ident) = self.ident { ident.to_tokens(tokens); tokens.append(":"); } self.ty.to_tokens(tokens); } } impl ToTokens for Visibility { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Visibility::Public => tokens.append("pub"), Visibility::Crate => { tokens.append("pub"); tokens.append("("); tokens.append("crate"); tokens.append(")"); } Visibility::Restricted(ref path) => { tokens.append("pub"); tokens.append("("); path.to_tokens(tokens); tokens.append(")"); } Visibility::Inherited => {} } } } } cpp_syn-0.12.0/src/derive.rs01006440000765000002400000006765130566610420014120 0ustar0000000000000000use super::*; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct DeriveInput { pub ident: Ident, pub vis: Visibility, pub attrs: Vec, pub generics: Generics, pub body: Body, pub span: Span, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Body { Enum(Vec), Struct(VariantData), } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use Generics; use attr::parsing::outer_attr; use data::parsing::{visibility, struct_body, enum_body}; use generics::parsing::generics; use ident::parsing::ident; named!(pub derive_input -> DeriveInput, add_span!(do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> which: alt!(keyword!("struct") | keyword!("enum")) >> id: ident >> generics: generics >> item: switch!(value!(which), "struct" => map!(struct_body, move |(wh, body)| DeriveInput { ident: id, vis: vis, attrs: attrs, generics: Generics { where_clause: wh, .. generics }, body: Body::Struct(body), span: DUMMY_SPAN, }) | "enum" => map!(enum_body, move |(wh, body)| DeriveInput { ident: id, vis: vis, attrs: attrs, generics: Generics { where_clause: wh, .. generics }, body: Body::Enum(body), span: DUMMY_SPAN, }) ) >> (item) ))); } #[cfg(feature = "printing")] mod printing { use super::*; use attr::FilterAttrs; use data::VariantData; use quote::{Tokens, ToTokens}; impl ToTokens for DeriveInput { fn to_tokens(&self, tokens: &mut Tokens) { for attr in self.attrs.outer() { attr.to_tokens(tokens); } self.vis.to_tokens(tokens); match self.body { Body::Enum(_) => tokens.append("enum"), Body::Struct(_) => tokens.append("struct"), } self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); match self.body { Body::Enum(ref variants) => { self.generics.where_clause.to_tokens(tokens); tokens.append("{"); for variant in variants { variant.to_tokens(tokens); tokens.append(","); } tokens.append("}"); } Body::Struct(ref variant_data) => { match *variant_data { VariantData::Struct(_) => { self.generics.where_clause.to_tokens(tokens); variant_data.to_tokens(tokens); // no semicolon } VariantData::Tuple(_) => { variant_data.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); tokens.append(";"); } VariantData::Unit => { self.generics.where_clause.to_tokens(tokens); tokens.append(";"); } } } } } } } cpp_syn-0.12.0/src/escape.rs01006440000765000002400000023162130501226120014055 0ustar0000000000000000use std::{char, str}; use std::num::ParseIntError; use synom::{IResult, ParseState}; pub fn cooked_string(input: ParseState) -> IResult { let mut s = String::new(); let mut chars = input.char_indices().peekable(); while let Some((byte_offset, ch)) = chars.next() { match ch { '"' => { return IResult::Done(input.advance(byte_offset), s); } '\r' => { if let Some((_, '\n')) = chars.next() { s.push('\n'); } else { break; } } '\\' => { match chars.next() { Some((_, 'x')) => { match backslash_x_char(&mut chars) { Some(ch) => s.push(ch), None => break, } } Some((_, 'n')) => s.push('\n'), Some((_, 'r')) => s.push('\r'), Some((_, 't')) => s.push('\t'), Some((_, '\\')) => s.push('\\'), Some((_, '0')) => s.push('\0'), Some((_, 'u')) => { match backslash_u(&mut chars) { Some(ch) => s.push(ch), None => break, } } Some((_, '\'')) => s.push('\''), Some((_, '"')) => s.push('"'), Some((_, '\n')) | Some((_, '\r')) => { while let Some(&(_, ch)) = chars.peek() { if ch.is_whitespace() { chars.next(); } else { break; } } } _ => break, } } ch => { s.push(ch); } } } IResult::Error } pub fn cooked_byte_string(mut input: ParseState) -> IResult> { let mut vec = Vec::new(); let mut bytes = input.bytes().enumerate(); 'outer: while let Some((offset, b)) = bytes.next() { match b { b'"' => { return IResult::Done(input.advance(offset), vec); } b'\r' => { if let Some((_, b'\n')) = bytes.next() { vec.push(b'\n'); } else { break; } } b'\\' => { match bytes.next() { Some((_, b'x')) => { match backslash_x_byte(&mut bytes) { Some(b) => vec.push(b), None => break, } } Some((_, b'n')) => vec.push(b'\n'), Some((_, b'r')) => vec.push(b'\r'), Some((_, b't')) => vec.push(b'\t'), Some((_, b'\\')) => vec.push(b'\\'), Some((_, b'0')) => vec.push(b'\0'), Some((_, b'\'')) => vec.push(b'\''), Some((_, b'"')) => vec.push(b'"'), Some((newline, b'\n')) | Some((newline, b'\r')) => { let rest = input.advance(newline + 1); for (offset, ch) in rest.char_indices() { if !ch.is_whitespace() { input = rest.advance(offset); bytes = input.bytes().enumerate(); continue 'outer; } } break; } _ => break, } } b if b < 0x80 => { vec.push(b); } _ => break, } } IResult::Error } pub fn cooked_char(input: ParseState) -> IResult { let mut chars = input.char_indices(); let ch = match chars.next().map(|(_, ch)| ch) { Some('\\') => { match chars.next().map(|(_, ch)| ch) { Some('x') => backslash_x_char(&mut chars), Some('n') => Some('\n'), Some('r') => Some('\r'), Some('t') => Some('\t'), Some('\\') => Some('\\'), Some('0') => Some('\0'), Some('u') => backslash_u(&mut chars), Some('\'') => Some('\''), Some('"') => Some('"'), _ => None, } } ch => ch, }; match (ch, chars.next()) { (Some(ch), Some((i, _))) => IResult::Done(input.advance(i), ch), (Some(ch), None) => IResult::Done(input.finish(), ch), _ => IResult::Error, } } pub fn cooked_byte(input: ParseState) -> IResult { let mut bytes = input.bytes().enumerate(); let b = match bytes.next().map(|(_, b)| b) { Some(b'\\') => { match bytes.next().map(|(_, b)| b) { Some(b'x') => backslash_x_byte(&mut bytes), Some(b'n') => Some(b'\n'), Some(b'r') => Some(b'\r'), Some(b't') => Some(b'\t'), Some(b'\\') => Some(b'\\'), Some(b'0') => Some(b'\0'), Some(b'\'') => Some(b'\''), Some(b'"') => Some(b'"'), _ => None, } } b => b, }; match b { Some(b) => { match bytes.next() { Some((offset, _)) => IResult::Done(input.advance(offset), b), None => IResult::Done(input.finish(), b), } } None => IResult::Error, } } pub fn raw_string(input: ParseState) -> IResult { let mut chars = input.char_indices(); let mut n = 0; while let Some((byte_offset, ch)) = chars.next() { match ch { '"' => { n = byte_offset; break; } '#' => {} _ => return IResult::Error, } } let mut s = String::new(); for (byte_offset, ch) in chars { match ch { '"' if input.advance(byte_offset + 1).starts_with(input.until(n)) => { let rest = input.advance(byte_offset + 1 + n); return IResult::Done(rest, (s, n)); } '\r' => {} _ => s.push(ch), } } IResult::Error } macro_rules! next_ch { ($chars:ident @ $pat:pat $(| $rest:pat)*) => { match $chars.next() { Some((_, ch)) => match ch { $pat $(| $rest)* => ch, _ => return None, }, None => return None, } }; } trait FromStrRadix: Sized { fn from_str_radix(src: &str, radix: u32) -> Result; } impl FromStrRadix for u8 { fn from_str_radix(src: &str, radix: u32) -> Result { u8::from_str_radix(src, radix) } } impl FromStrRadix for u32 { fn from_str_radix(src: &str, radix: u32) -> Result { u32::from_str_radix(src, radix) } } macro_rules! from_hex { ($($ch:ident)+) => {{ let hex_bytes = &[$($ch as u8),*]; let hex_str = str::from_utf8(hex_bytes).unwrap(); FromStrRadix::from_str_radix(hex_str, 16).unwrap() }}; } #[cfg_attr(feature = "clippy", allow(diverging_sub_expression))] fn backslash_x_char(chars: &mut I) -> Option where I: Iterator { let a = next_ch!(chars @ '0'...'7'); let b = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F'); char::from_u32(from_hex!(a b)) } #[cfg_attr(feature = "clippy", allow(diverging_sub_expression))] fn backslash_x_byte(chars: &mut I) -> Option where I: Iterator { let a = next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F'); let b = next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F'); Some(from_hex!(a b)) } #[cfg_attr(feature = "clippy", allow(diverging_sub_expression, many_single_char_names))] fn backslash_u(chars: &mut I) -> Option where I: Iterator { next_ch!(chars @ '{'); let a = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F'); let b = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}'); if b == '}' { return char::from_u32(from_hex!(a)); } let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}'); if c == '}' { return char::from_u32(from_hex!(a b)); } let d = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}'); if d == '}' { return char::from_u32(from_hex!(a b c)); } let e = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}'); if e == '}' { return char::from_u32(from_hex!(a b c d)); } let f = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}'); if f == '}' { return char::from_u32(from_hex!(a b c d e)); } next_ch!(chars @ '}'); char::from_u32(from_hex!(a b c d e f)) } #[test] fn test_cooked_string() { let input = "\\x62 \\\n \\u{7} \\u{64} \\u{bf5} \\u{12ba} \\u{1F395} \\u{102345}\""; let expected = "\x62 \u{7} \u{64} \u{bf5} \u{12ba} \u{1F395} \u{102345}"; assert!(cooked_string(ParseState::new(input)).test_looks_like("\"", &expected.to_string())); } #[test] fn test_cooked_byte_string() { let input = "\\x62 \\\n \\xEF\""; let expected = b"\x62 \xEF"; assert!(cooked_byte_string(ParseState::new(input)).test_looks_like("\"", &expected.to_vec())); } cpp_syn-0.12.0/src/expr.rs01006440000765000002400000161614130566610420013613 0ustar0000000000000000use super::*; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Expr { pub node: ExprKind, pub attrs: Vec, pub span: Span, } impl Expr { pub fn new(node: ExprKind, span: Span) -> Expr { Expr { node: node, attrs: Vec::new(), span: span, } } } impl From> for Expr { fn from(spanned: Spanned) -> Expr { Expr::new(spanned.node, spanned.span) } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ExprKind { /// A `box x` expression. Box(Box), /// First expr is the place; second expr is the value. InPlace(Box, Box), /// An array (`[a, b, c, d]`) Array(Vec), /// A function call /// /// The first field resolves to the function itself, /// and the second field is the list of arguments Call(Box, Vec), /// A method call (`x.foo::(a, b, c, d)`) /// /// The `Ident` is the identifier for the method name. /// The vector of `Ty`s are the ascripted type parameters for the method /// (within the angle brackets). /// /// The first element of the vector of `Expr`s is the expression that evaluates /// to the object on which the method is being called on (the receiver), /// and the remaining elements are the rest of the arguments. /// /// Thus, `x.foo::(a, b, c, d)` is represented as /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. MethodCall(Ident, Vec, Vec), /// A tuple (`(a, b, c, d)`) Tup(Vec), /// A binary operation (For example: `a + b`, `a * b`) Binary(BinOp, Box, Box), /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, Box), /// A literal (For example: `1`, `"foo"`) Lit(Lit), /// A cast (`foo as f64`) Cast(Box, Box), /// Type ascription (`foo: f64`) Type(Box, Box), /// An `if` block, with an optional else block /// /// `if expr { block } else { expr }` If(Box, Block, Option>), /// An `if let` expression with an optional else block /// /// `if let pat = expr { block } else { expr }` /// /// This is desugared to a `match` expression. IfLet(Box, Box, Block, Option>), /// A while loop, with an optional label /// /// `'label: while expr { block }` While(Box, Block, Option), /// A while-let loop, with an optional label /// /// `'label: while let pat = expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. WhileLet(Box, Box, Block, Option), /// A for loop, with an optional label /// /// `'label: for pat in expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. ForLoop(Box, Box, Block, Option), /// Conditionless loop (can be exited with break, continue, or return) /// /// `'label: loop { block }` Loop(Block, Option), /// A `match` block. Match(Box, Vec), /// A closure (for example, `move |a, b, c| a + b + c`) Closure(CaptureBy, Box, Box), /// A block (`{ ... }` or `unsafe { ... }`) Block(Unsafety, Block), /// An assignment (`a = foo()`) Assign(Box, Box), /// An assignment with an operator /// /// For example, `a += 1`. AssignOp(BinOp, Box, Box), /// Access of a named struct field (`obj.foo`) Field(Box, Ident), /// Access of an unnamed field of a struct or tuple-struct /// /// For example, `foo.0`. TupField(Box, usize), /// An indexing operation (`foo[2]`) Index(Box, Box), /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`) Range(Option>, Option>, RangeLimits), /// Variable reference, possibly containing `::` and/or type /// parameters, e.g. foo::bar::. /// /// Optionally "qualified", /// E.g. ` as SomeTrait>::SomeType`. Path(Option, Path), /// A referencing operation (`&a` or `&mut a`) AddrOf(Mutability, Box), /// A `break`, with an optional label to break, and an optional expression Break(Option, Option>), /// A `continue`, with an optional label Continue(Option), /// A `return`, with an optional value to be returned Ret(Option>), /// A macro invocation; pre-expansion Mac(Mac), /// A struct literal expression. /// /// For example, `Foo {x: 1, y: 2}`, or /// `Foo {x: 1, .. base}`, where `base` is the `Option`. Struct(Path, Vec, Option>), /// An array literal constructed from one repeated element. /// /// For example, `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. Repeat(Box, Box), /// No-op: used solely so we can pretty-print faithfully Paren(Box), /// `expr?` Try(Box), } impl ExprKind { pub fn span(self, span: Span) -> Expr { Expr::new(self, span) } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct FieldValue { pub ident: Ident, pub expr: Expr, pub is_shorthand: bool, pub attrs: Vec, } /// A Block (`{ .. }`). /// /// E.g. `{ .. }` as in `fn foo() { .. }` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Block { /// Statements in a block pub stmts: Vec, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Stmt { /// A local (let) binding. Local(Box), /// An item definition. Item(Box), /// Expr without trailing semi-colon. Expr(Box), Semi(Box), Mac(Box<(Mac, MacStmtStyle, Vec)>), } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum MacStmtStyle { /// The macro statement had a trailing semicolon, e.g. `foo! { ... };` /// `foo!(...);`, `foo![...];` Semicolon, /// The macro statement had braces; e.g. foo! { ... } Braces, /// The macro statement had parentheses or brackets and no semicolon; e.g. /// `foo!(...)`. All of these will end up being converted into macro /// expressions. NoBraces, } /// Local represents a `let` statement, e.g., `let : = ;` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Local { pub pat: Box, pub ty: Option>, /// Initializer expression to set the value, if any pub init: Option>, pub attrs: Vec, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] // Clippy false positive // https://github.com/Manishearth/rust-clippy/issues/1241 #[cfg_attr(feature = "clippy", allow(enum_variant_names))] pub enum Pat { /// Represents a wildcard pattern (`_`) Wild, /// A `Pat::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`), /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens /// during name resolution. Ident(BindingMode, Ident, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. /// The `bool` is `true` in the presence of a `..`. Struct(Path, Vec, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. /// 0 <= position <= subpats.len() TupleStruct(Path, Vec, Option), /// A possibly qualified path pattern. /// Unquailfied path patterns `A::B::C` can legally refer to variants, structs, constants /// or associated constants. Quailfied path patterns `::B::C`/`::B::C` can /// only legally refer to associated constants. Path(Option, Path), /// A tuple pattern `(a, b)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. /// 0 <= position <= subpats.len() Tuple(Vec, Option), /// A `box` pattern Box(Box), /// A reference pattern, e.g. `&mut (a, b)` Ref(Box, Mutability), /// A literal Lit(Box), /// A range pattern, e.g. `1...2` Range(Box, Box), /// `[a, b, ..i, y, z]` is represented as: /// `Pat::Slice(box [a, b], Some(i), box [y, z])` Slice(Vec, Option>, Vec), /// A macro pattern; pre-expansion Mac(Mac), } /// An arm of a 'match'. /// /// E.g. `0...10 => { println!("match!") }` as in /// /// ```rust,ignore /// match n { /// 0...10 => { println!("match!") }, /// // .. /// } /// ``` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Arm { pub attrs: Vec, pub pats: Vec, pub guard: Option>, pub body: Box, } /// A capture clause #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum CaptureBy { Value, Ref, } /// Limit types of a range (inclusive or exclusive) #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum RangeLimits { /// Inclusive at the beginning, exclusive at the end HalfOpen, /// Inclusive at the beginning and end Closed, } /// A single field in a struct pattern /// /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` /// are treated the same as `x: x, y: ref y, z: ref mut z`, /// except `is_shorthand` is true #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct FieldPat { /// The identifier for the field pub ident: Ident, /// The pattern the field is destructured to pub pat: Box, pub is_shorthand: bool, pub attrs: Vec, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum BindingMode { ByRef(Mutability), ByValue(Mutability), } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use {BinOp, Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, Mac, TokenTree, Ty, UnOp, Unsafety}; use attr::parsing::outer_attr; use generics::parsing::lifetime; use ident::parsing::{ident, wordlike}; use item::parsing::item; use lit::parsing::{digits, lit}; use mac::parsing::{mac, token_trees}; use synom::IResult::{self, Error}; use synom::ParseState; use op::parsing::{assign_op, binop, unop}; use ty::parsing::{mutability, path, qpath, ty, unsafety}; // Struct literals are ambiguous in certain positions // https://github.com/rust-lang/rfcs/pull/92 macro_rules! named_ambiguous_expr { ($name:ident -> $o:ty, $allow_struct:ident, $submac:ident!( $($args:tt)* )) => { fn $name(i: $crate::synom::ParseState, $allow_struct: bool) -> $crate::synom::IResult<$crate::synom::ParseState, $o> { $submac!(i, $($args)*) } }; } macro_rules! ambiguous_expr { ($i:expr, $allow_struct:ident) => { ambiguous_expr($i, $allow_struct, true) }; } named!(pub expr -> Expr, ambiguous_expr!(true)); named!(expr_no_struct -> Expr, ambiguous_expr!(false)); fn ambiguous_expr(i: ParseState, allow_struct: bool, allow_block: bool) -> IResult { do_parse!( i, mut e: map!(spanned!(alt!( expr_lit // must be before expr_struct | cond_reduce!(allow_struct, expr_struct) // must be before expr_path | expr_paren // must be before expr_tup | expr_mac // must be before expr_path | call!(expr_break, allow_struct) // must be before expr_path | expr_continue // must be before expr_path | call!(expr_ret, allow_struct) // must be before expr_path | call!(expr_box, allow_struct) | expr_in_place | expr_array | expr_tup | call!(expr_unary, allow_struct) | expr_if | expr_while | expr_for_loop | expr_loop | expr_match | call!(expr_closure, allow_struct) | cond_reduce!(allow_block, expr_block) | call!(expr_range, allow_struct) | expr_path | call!(expr_addr_of, allow_struct) | expr_repeat )), >>::from) >> many0!(alt!( tap!(args: spanned!(and_call) => { let span = e.span; e = Spanned { node: ExprKind::Call(Box::new(e), args.node), span: span.extend(args.span), }.into(); }) | tap!(more: spanned!(and_method_call) => { let span = e.span; let new_span = more.span; let (method, ascript, mut args) = more.node; args.insert(0, e); e = Spanned { node: ExprKind::MethodCall(method, ascript, args), span: span.extend(new_span), }.into(); }) | tap!(more: spanned!(call!(and_binary, allow_struct)) => { let (span, new_span) = (e.span, more.span); let (op, other) = more.node; e = Spanned { node: ExprKind::Binary(op, Box::new(e), Box::new(other)), span: span.extend(new_span), }.into(); }) | tap!(ty: spanned!(and_cast) => { let span = e.span; e = Spanned { node: ExprKind::Cast(Box::new(e), Box::new(ty.node)), span: span.extend(ty.span), }.into(); }) | tap!(ty: spanned!(and_ascription) => { let span = e.span; e = Spanned { node: ExprKind::Type(Box::new(e), Box::new(ty.node)), span: span.extend(ty.span), }.into(); }) | tap!(v: spanned!(call!(and_assign, allow_struct)) => { let span = e.span; e = Spanned { node: ExprKind::Assign(Box::new(e), Box::new(v.node)), span: span.extend(v.span), }.into(); }) | tap!(more: spanned!(call!(and_assign_op, allow_struct)) => { let (span, new_span) = (e.span, more.span); let (op, v) = more.node; e = Spanned { node: ExprKind::AssignOp(op, Box::new(e), Box::new(v)), span: span.extend(new_span), }.into(); }) | tap!(field: spanned!(and_field) => { let span = e.span; e = Spanned { node: ExprKind::Field(Box::new(e), field.node), span: span.extend(field.span), }.into(); }) | tap!(field: spanned!(and_tup_field) => { let span = e.span; e = Spanned { node: ExprKind::TupField(Box::new(e), field.node as usize), span: span.extend(field.span), }.into(); }) | tap!(i: spanned!(and_index) => { let span = e.span; e = Spanned { node: ExprKind::Index(Box::new(e), Box::new(i.node)), span: span.extend(i.span), }.into(); }) | tap!(more: spanned!(call!(and_range, allow_struct)) => { let (span, new_span) = (e.span, more.span); let (limits, hi) = more.node; e = Spanned { node: ExprKind::Range(Some(Box::new(e)), hi.map(Box::new), limits), span: span.extend(new_span), }.into(); }) | tap!(try: spanned!(punct!("?")) => { let span = e.span; e = Spanned { node: ExprKind::Try(Box::new(e)), span: span.extend(try.span), }.into(); }) )) >> (e) ) } named!(expr_mac -> ExprKind, map!(mac, ExprKind::Mac)); named!(expr_paren -> ExprKind, do_parse!( punct!("(") >> e: expr >> punct!(")") >> (ExprKind::Paren(Box::new(e))) )); named_ambiguous_expr!(expr_box -> ExprKind, allow_struct, do_parse!( keyword!("box") >> inner: ambiguous_expr!(allow_struct) >> (ExprKind::Box(Box::new(inner))) )); named!(expr_in_place -> ExprKind, do_parse!( keyword!("in") >> place: expr_no_struct >> value: spanned!(delimited!(punct!("{"), within_block, punct!("}"))) >> (ExprKind::InPlace( Box::new(place), Box::new(ExprKind::Block(Unsafety::Normal, Block { stmts: value.node, }).span(value.span)), )) )); named!(expr_array -> ExprKind, do_parse!( punct!("[") >> elems: terminated_list!(punct!(","), expr) >> punct!("]") >> (ExprKind::Array(elems)) )); named!(and_call -> Vec, do_parse!( punct!("(") >> args: terminated_list!(punct!(","), expr) >> punct!(")") >> (args) )); named!(and_method_call -> (Ident, Vec, Vec), do_parse!( punct!(".") >> method: ident >> ascript: opt_vec!(preceded!( punct!("::"), delimited!( punct!("<"), terminated_list!(punct!(","), ty), punct!(">") ) )) >> punct!("(") >> args: terminated_list!(punct!(","), expr) >> punct!(")") >> (method, ascript, args) )); named!(expr_tup -> ExprKind, do_parse!( punct!("(") >> elems: terminated_list!(punct!(","), expr) >> punct!(")") >> (ExprKind::Tup(elems)) )); named_ambiguous_expr!(and_binary -> (BinOp, Expr), allow_struct, tuple!( binop, ambiguous_expr!(allow_struct) )); named_ambiguous_expr!(expr_unary -> ExprKind, allow_struct, do_parse!( operator: unop >> operand: ambiguous_expr!(allow_struct) >> (ExprKind::Unary(operator, Box::new(operand))) )); named!(expr_lit -> ExprKind, map!(lit, ExprKind::Lit)); named!(and_cast -> Ty, do_parse!( keyword!("as") >> ty: ty >> (ty) )); named!(and_ascription -> Ty, preceded!(punct!(":"), ty)); enum Cond { Let(Pat, Expr), Expr(Expr), } named!(cond -> Cond, alt!( do_parse!( keyword!("let") >> pat: pat >> punct!("=") >> value: expr_no_struct >> (Cond::Let(pat, value)) ) | map!(expr_no_struct, Cond::Expr) )); named!(expr_if -> ExprKind, do_parse!( keyword!("if") >> cond: cond >> then_block: block >> else_block: option!(spanned!(preceded!( keyword!("else"), alt!( expr_if | do_parse!( else_block: block >> (ExprKind::Block(Unsafety::Normal, else_block)) ) ) ))) >> (match cond { Cond::Let(pat, expr) => ExprKind::IfLet( Box::new(pat), Box::new(expr), then_block, else_block.map(|Spanned{ node, span }| Box::new(node.span(span))), ), Cond::Expr(cond) => ExprKind::If( Box::new(cond), then_block, else_block.map(|Spanned{ node, span }| Box::new(node.span(span))), ), }) )); named!(expr_for_loop -> ExprKind, do_parse!( lbl: option!(terminated!(label, punct!(":"))) >> keyword!("for") >> pat: pat >> keyword!("in") >> expr: expr_no_struct >> loop_block: block >> (ExprKind::ForLoop(Box::new(pat), Box::new(expr), loop_block, lbl)) )); named!(expr_loop -> ExprKind, do_parse!( lbl: option!(terminated!(label, punct!(":"))) >> keyword!("loop") >> loop_block: block >> (ExprKind::Loop(loop_block, lbl)) )); named!(expr_match -> ExprKind, do_parse!( keyword!("match") >> obj: expr_no_struct >> punct!("{") >> mut arms: many0!(do_parse!( arm: match_arm >> cond!(arm_requires_comma(&arm), punct!(",")) >> cond!(!arm_requires_comma(&arm), option!(punct!(","))) >> (arm) )) >> last_arm: option!(match_arm) >> punct!("}") >> (ExprKind::Match(Box::new(obj), { arms.extend(last_arm); arms })) )); fn arm_requires_comma(arm: &Arm) -> bool { if let ExprKind::Block(Unsafety::Normal, _) = arm.body.node { false } else { true } } named!(match_arm -> Arm, do_parse!( attrs: many0!(outer_attr) >> pats: separated_nonempty_list!(punct!("|"), pat) >> guard: option!(preceded!(keyword!("if"), expr)) >> punct!("=>") >> body: alt!( map!(spanned!(block), |Spanned{ node, span }| ExprKind::Block(Unsafety::Normal, node).span(span)) | expr ) >> (Arm { attrs: attrs, pats: pats, guard: guard.map(Box::new), body: Box::new(body), }) )); named_ambiguous_expr!(expr_closure -> ExprKind, allow_struct, do_parse!( capture: capture_by >> punct!("|") >> inputs: terminated_list!(punct!(","), closure_arg) >> punct!("|") >> ret_and_body: alt!( do_parse!( punct!("->") >> ty: ty >> body: spanned!(block) >> (FunctionRetTy::Ty(ty), ExprKind::Block(Unsafety::Normal, body.node).span(body.span)) ) | map!(ambiguous_expr!(allow_struct), |e| (FunctionRetTy::Default, e)) ) >> (ExprKind::Closure( capture, Box::new(FnDecl { inputs: inputs, output: ret_and_body.0, variadic: false, }), Box::new(ret_and_body.1), )) )); named!(closure_arg -> FnArg, do_parse!( pat: pat >> ty: option!(preceded!(punct!(":"), ty)) >> (FnArg::Captured(pat, ty.unwrap_or(Ty::Infer))) )); named!(expr_while -> ExprKind, do_parse!( lbl: option!(terminated!(label, punct!(":"))) >> keyword!("while") >> cond: cond >> while_block: block >> (match cond { Cond::Let(pat, expr) => ExprKind::WhileLet( Box::new(pat), Box::new(expr), while_block, lbl, ), Cond::Expr(cond) => ExprKind::While( Box::new(cond), while_block, lbl, ), }) )); named!(expr_continue -> ExprKind, do_parse!( keyword!("continue") >> lbl: option!(label) >> (ExprKind::Continue(lbl)) )); named_ambiguous_expr!(expr_break -> ExprKind, allow_struct, do_parse!( keyword!("break") >> lbl: option!(label) >> val: option!(call!(ambiguous_expr, allow_struct, false)) >> (ExprKind::Break(lbl, val.map(Box::new))) )); named_ambiguous_expr!(expr_ret -> ExprKind, allow_struct, do_parse!( keyword!("return") >> ret_value: option!(ambiguous_expr!(allow_struct)) >> (ExprKind::Ret(ret_value.map(Box::new))) )); named!(expr_struct -> ExprKind, do_parse!( path: path >> punct!("{") >> fields: separated_list!(punct!(","), field_value) >> base: option!(do_parse!( cond!(!fields.is_empty(), punct!(",")) >> punct!("..") >> base: expr >> (base) )) >> cond!(!fields.is_empty() && base.is_none(), option!(punct!(","))) >> punct!("}") >> (ExprKind::Struct(path, fields, base.map(Box::new))) )); named!(field_value -> FieldValue, alt!( do_parse!( name: wordlike >> punct!(":") >> value: expr >> (FieldValue { ident: name, expr: value, is_shorthand: false, attrs: Vec::new(), }) ) | map!(spanned!(ident), |Spanned{ node, span }: Spanned| FieldValue { ident: node.clone(), expr: ExprKind::Path(None, node.into()).span(span), is_shorthand: true, attrs: Vec::new(), }) )); named!(expr_repeat -> ExprKind, do_parse!( punct!("[") >> value: expr >> punct!(";") >> times: expr >> punct!("]") >> (ExprKind::Repeat(Box::new(value), Box::new(times))) )); named!(expr_block -> ExprKind, do_parse!( rules: unsafety >> b: block >> (ExprKind::Block(rules, Block { stmts: b.stmts, })) )); named_ambiguous_expr!(expr_range -> ExprKind, allow_struct, do_parse!( limits: range_limits >> hi: option!(ambiguous_expr!(allow_struct)) >> (ExprKind::Range(None, hi.map(Box::new), limits)) )); named!(range_limits -> RangeLimits, alt!( punct!("...") => { |_| RangeLimits::Closed } | punct!("..") => { |_| RangeLimits::HalfOpen } )); named!(expr_path -> ExprKind, map!(qpath, |(qself, path)| ExprKind::Path(qself, path))); named_ambiguous_expr!(expr_addr_of -> ExprKind, allow_struct, do_parse!( punct!("&") >> mutability: mutability >> expr: ambiguous_expr!(allow_struct) >> (ExprKind::AddrOf(mutability, Box::new(expr))) )); named_ambiguous_expr!(and_assign -> Expr, allow_struct, preceded!( punct!("="), ambiguous_expr!(allow_struct) )); named_ambiguous_expr!(and_assign_op -> (BinOp, Expr), allow_struct, tuple!( assign_op, ambiguous_expr!(allow_struct) )); named!(and_field -> Ident, preceded!(punct!("."), ident)); named!(and_tup_field -> u64, preceded!(punct!("."), digits)); named!(and_index -> Expr, delimited!(punct!("["), expr, punct!("]"))); named_ambiguous_expr!(and_range -> (RangeLimits, Option), allow_struct, tuple!( range_limits, option!(call!(ambiguous_expr, allow_struct, false)) )); named!(pub block -> Block, do_parse!( punct!("{") >> stmts: within_block >> punct!("}") >> (Block { stmts: stmts, }) )); named!(pub within_block -> Vec, do_parse!( many0!(punct!(";")) >> mut standalone: many0!(terminated!(standalone_stmt, many0!(punct!(";")))) >> last: option!(expr) >> (match last { None => standalone, Some(last) => { standalone.push(Stmt::Expr(Box::new(last))); standalone } }) )); named!(standalone_stmt -> Stmt, alt!( stmt_mac | stmt_local | stmt_item | stmt_expr )); named!(stmt_mac -> Stmt, do_parse!( attrs: many0!(outer_attr) >> what: path >> punct!("!") >> // Only parse braces here; paren and bracket will get parsed as // expression statements tts: spanned!(delimited!( punct!("{"), token_trees, punct!("}") )) >> semi: option!(punct!(";")) >> (Stmt::Mac(Box::new(( Mac { path: what, tts: vec![TokenTree::Delimited(Delimited { delim: DelimToken::Brace, tts: tts.node, }, tts.span)], }, if semi.is_some() { MacStmtStyle::Semicolon } else { MacStmtStyle::Braces }, attrs, )))) )); named!(stmt_local -> Stmt, do_parse!( attrs: many0!(outer_attr) >> keyword!("let") >> pat: pat >> ty: option!(preceded!(punct!(":"), ty)) >> init: option!(preceded!(punct!("="), expr)) >> punct!(";") >> (Stmt::Local(Box::new(Local { pat: Box::new(pat), ty: ty.map(Box::new), init: init.map(Box::new), attrs: attrs, }))) )); named!(stmt_item -> Stmt, map!(item, |i| Stmt::Item(Box::new(i)))); fn requires_semi(e: &Expr) -> bool { match e.node { ExprKind::If(_, _, _) | ExprKind::IfLet(_, _, _, _) | ExprKind::While(_, _, _) | ExprKind::WhileLet(_, _, _, _) | ExprKind::ForLoop(_, _, _, _) | ExprKind::Loop(_, _) | ExprKind::Match(_, _) | ExprKind::Block(_, _) => false, _ => true, } } named!(stmt_expr -> Stmt, do_parse!( attrs: many0!(outer_attr) >> mut e: expr >> semi: option!(punct!(";")) >> ({ e.attrs = attrs; if semi.is_some() { Stmt::Semi(Box::new(e)) } else if requires_semi(&e) { return Error; } else { Stmt::Expr(Box::new(e)) } }) )); named!(pub pat -> Pat, alt!( pat_wild // must be before pat_ident | pat_box // must be before pat_ident | pat_range // must be before pat_lit | pat_tuple_struct // must be before pat_ident | pat_struct // must be before pat_ident | pat_mac // must be before pat_ident | pat_lit // must be before pat_ident | pat_ident // must be before pat_path | pat_path | pat_tuple | pat_ref | pat_slice )); named!(pat_mac -> Pat, map!(mac, Pat::Mac)); named!(pat_wild -> Pat, map!(keyword!("_"), |_| Pat::Wild)); named!(pat_box -> Pat, do_parse!( keyword!("box") >> pat: pat >> (Pat::Box(Box::new(pat))) )); named!(pat_ident -> Pat, do_parse!( mode: option!(keyword!("ref")) >> mutability: mutability >> name: alt!( ident | keyword!("self") => { Into::into } ) >> not!(punct!("<")) >> not!(punct!("::")) >> subpat: option!(preceded!(punct!("@"), pat)) >> (Pat::Ident( if mode.is_some() { BindingMode::ByRef(mutability) } else { BindingMode::ByValue(mutability) }, name, subpat.map(Box::new), )) )); named!(pat_tuple_struct -> Pat, do_parse!( path: path >> tuple: pat_tuple_helper >> (Pat::TupleStruct(path, tuple.0, tuple.1)) )); named!(pat_struct -> Pat, do_parse!( path: path >> punct!("{") >> fields: separated_list!(punct!(","), field_pat) >> more: option!(preceded!( cond!(!fields.is_empty(), punct!(",")), punct!("..") )) >> cond!(!fields.is_empty() && more.is_none(), option!(punct!(","))) >> punct!("}") >> (Pat::Struct(path, fields, more.is_some())) )); named!(field_pat -> FieldPat, alt!( do_parse!( ident: wordlike >> punct!(":") >> pat: pat >> (FieldPat { ident: ident, pat: Box::new(pat), is_shorthand: false, attrs: Vec::new(), }) ) | do_parse!( boxed: option!(keyword!("box")) >> mode: option!(keyword!("ref")) >> mutability: mutability >> ident: ident >> ({ let mut pat = Pat::Ident( if mode.is_some() { BindingMode::ByRef(mutability) } else { BindingMode::ByValue(mutability) }, ident.clone(), None, ); if boxed.is_some() { pat = Pat::Box(Box::new(pat)); } FieldPat { ident: ident, pat: Box::new(pat), is_shorthand: true, attrs: Vec::new(), } }) ) )); named!(pat_path -> Pat, map!(qpath, |(qself, path)| Pat::Path(qself, path))); named!(pat_tuple -> Pat, map!( pat_tuple_helper, |(pats, dotdot)| Pat::Tuple(pats, dotdot) )); named!(pat_tuple_helper -> (Vec, Option), do_parse!( punct!("(") >> mut elems: separated_list!(punct!(","), pat) >> dotdot: option!(do_parse!( cond!(!elems.is_empty(), punct!(",")) >> punct!("..") >> rest: many0!(preceded!(punct!(","), pat)) >> cond!(!rest.is_empty(), option!(punct!(","))) >> (rest) )) >> cond!(!elems.is_empty() && dotdot.is_none(), option!(punct!(","))) >> punct!(")") >> (match dotdot { Some(rest) => { let pos = elems.len(); elems.extend(rest); (elems, Some(pos)) } None => (elems, None), }) )); named!(pat_ref -> Pat, do_parse!( punct!("&") >> mutability: mutability >> pat: pat >> (Pat::Ref(Box::new(pat), mutability)) )); named!(pat_lit -> Pat, do_parse!( lit: pat_lit_expr >> (if let ExprKind::Path(_, _) = lit.node { return IResult::Error; // these need to be parsed by pat_path } else { Pat::Lit(Box::new(lit)) }) )); named!(pat_range -> Pat, do_parse!( lo: pat_lit_expr >> punct!("...") >> hi: pat_lit_expr >> (Pat::Range(Box::new(lo), Box::new(hi))) )); named!(pat_lit_expr -> Expr, map!(spanned!(do_parse!( neg: option!(punct!("-")) >> v: spanned!(alt!( lit => { ExprKind::Lit } | path => { |p| ExprKind::Path(None, p) } )) >> (if neg.is_some() { ExprKind::Unary(UnOp::Neg, Box::new(v.into())) } else { v.node }) )), >>::from)); named!(pat_slice -> Pat, do_parse!( punct!("[") >> mut before: separated_list!(punct!(","), pat) >> after: option!(do_parse!( comma_before_dots: option!(cond_reduce!(!before.is_empty(), punct!(","))) >> punct!("..") >> after: many0!(preceded!(punct!(","), pat)) >> cond!(!after.is_empty(), option!(punct!(","))) >> (comma_before_dots.is_some(), after) )) >> cond!(after.is_none(), option!(punct!(","))) >> punct!("]") >> (match after { None => Pat::Slice(before, None, Vec::new()), Some((true, after)) => { if before.is_empty() { return IResult::Error; } Pat::Slice(before, Some(Box::new(Pat::Wild)), after) } Some((false, after)) => { let rest = before.pop().unwrap_or(Pat::Wild); Pat::Slice(before, Some(Box::new(rest)), after) } }) )); named!(capture_by -> CaptureBy, alt!( keyword!("move") => { |_| CaptureBy::Value } | epsilon!() => { |_| CaptureBy::Ref } )); named!(label -> Ident, map!(lifetime, |lt: Lifetime| lt.ident)); } #[cfg(feature = "printing")] mod printing { use super::*; use {FnArg, FunctionRetTy, Mutability, Ty, Unsafety}; use attr::FilterAttrs; use quote::{Tokens, ToTokens}; impl ToTokens for Expr { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); match self.node { ExprKind::Box(ref inner) => { tokens.append("box"); inner.to_tokens(tokens); } ExprKind::InPlace(ref place, ref value) => { tokens.append("in"); place.to_tokens(tokens); value.to_tokens(tokens); } ExprKind::Array(ref tys) => { tokens.append("["); tokens.append_separated(tys, ","); tokens.append("]"); } ExprKind::Call(ref func, ref args) => { func.to_tokens(tokens); tokens.append("("); tokens.append_separated(args, ","); tokens.append(")"); } ExprKind::MethodCall(ref ident, ref ascript, ref args) => { args[0].to_tokens(tokens); tokens.append("."); ident.to_tokens(tokens); if !ascript.is_empty() { tokens.append("::"); tokens.append("<"); tokens.append_separated(ascript, ","); tokens.append(">"); } tokens.append("("); tokens.append_separated(&args[1..], ","); tokens.append(")"); } ExprKind::Tup(ref fields) => { tokens.append("("); tokens.append_separated(fields, ","); if fields.len() == 1 { tokens.append(","); } tokens.append(")"); } ExprKind::Binary(op, ref left, ref right) => { left.to_tokens(tokens); op.to_tokens(tokens); right.to_tokens(tokens); } ExprKind::Unary(op, ref expr) => { op.to_tokens(tokens); expr.to_tokens(tokens); } ExprKind::Lit(ref lit) => lit.to_tokens(tokens), ExprKind::Cast(ref expr, ref ty) => { expr.to_tokens(tokens); tokens.append("as"); ty.to_tokens(tokens); } ExprKind::Type(ref expr, ref ty) => { expr.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); } ExprKind::If(ref cond, ref then_block, ref else_block) => { tokens.append("if"); cond.to_tokens(tokens); then_block.to_tokens(tokens); if let Some(ref else_block) = *else_block { tokens.append("else"); else_block.to_tokens(tokens); } } ExprKind::IfLet(ref pat, ref expr, ref then_block, ref else_block) => { tokens.append("if"); tokens.append("let"); pat.to_tokens(tokens); tokens.append("="); expr.to_tokens(tokens); then_block.to_tokens(tokens); if let Some(ref else_block) = *else_block { tokens.append("else"); else_block.to_tokens(tokens); } } ExprKind::While(ref cond, ref body, ref label) => { if let Some(ref label) = *label { label.to_tokens(tokens); tokens.append(":"); } tokens.append("while"); cond.to_tokens(tokens); body.to_tokens(tokens); } ExprKind::WhileLet(ref pat, ref expr, ref body, ref label) => { if let Some(ref label) = *label { label.to_tokens(tokens); tokens.append(":"); } tokens.append("while"); tokens.append("let"); pat.to_tokens(tokens); tokens.append("="); expr.to_tokens(tokens); body.to_tokens(tokens); } ExprKind::ForLoop(ref pat, ref expr, ref body, ref label) => { if let Some(ref label) = *label { label.to_tokens(tokens); tokens.append(":"); } tokens.append("for"); pat.to_tokens(tokens); tokens.append("in"); expr.to_tokens(tokens); body.to_tokens(tokens); } ExprKind::Loop(ref body, ref label) => { if let Some(ref label) = *label { label.to_tokens(tokens); tokens.append(":"); } tokens.append("loop"); body.to_tokens(tokens); } ExprKind::Match(ref expr, ref arms) => { tokens.append("match"); expr.to_tokens(tokens); tokens.append("{"); tokens.append_all(arms); tokens.append("}"); } ExprKind::Closure(capture, ref decl, ref expr) => { capture.to_tokens(tokens); tokens.append("|"); for (i, input) in decl.inputs.iter().enumerate() { if i > 0 { tokens.append(","); } match *input { FnArg::Captured(ref pat, Ty::Infer) => { pat.to_tokens(tokens); } _ => input.to_tokens(tokens), } } tokens.append("|"); match decl.output { FunctionRetTy::Default => { /* nothing */ } FunctionRetTy::Ty(ref ty) => { tokens.append("->"); ty.to_tokens(tokens); } } expr.to_tokens(tokens); } ExprKind::Block(rules, ref block) => { rules.to_tokens(tokens); block.to_tokens(tokens); } ExprKind::Assign(ref var, ref expr) => { var.to_tokens(tokens); tokens.append("="); expr.to_tokens(tokens); } ExprKind::AssignOp(op, ref var, ref expr) => { var.to_tokens(tokens); tokens.append(op.assign_op().unwrap()); expr.to_tokens(tokens); } ExprKind::Field(ref expr, ref field) => { expr.to_tokens(tokens); tokens.append("."); field.to_tokens(tokens); } ExprKind::TupField(ref expr, field) => { expr.to_tokens(tokens); tokens.append("."); tokens.append(&field.to_string()); } ExprKind::Index(ref expr, ref index) => { expr.to_tokens(tokens); tokens.append("["); index.to_tokens(tokens); tokens.append("]"); } ExprKind::Range(ref from, ref to, limits) => { from.to_tokens(tokens); match limits { RangeLimits::HalfOpen => tokens.append(".."), RangeLimits::Closed => tokens.append("..."), } to.to_tokens(tokens); } ExprKind::Path(None, ref path) => path.to_tokens(tokens), ExprKind::Path(Some(ref qself), ref path) => { tokens.append("<"); qself.ty.to_tokens(tokens); if qself.position > 0 { tokens.append("as"); for (i, segment) in path.segments .iter() .take(qself.position) .enumerate() { if i > 0 || path.global { tokens.append("::"); } segment.to_tokens(tokens); } } tokens.append(">"); for segment in path.segments.iter().skip(qself.position) { tokens.append("::"); segment.to_tokens(tokens); } } ExprKind::AddrOf(mutability, ref expr) => { tokens.append("&"); mutability.to_tokens(tokens); expr.to_tokens(tokens); } ExprKind::Break(ref opt_label, ref opt_val) => { tokens.append("break"); opt_label.to_tokens(tokens); opt_val.to_tokens(tokens); } ExprKind::Continue(ref opt_label) => { tokens.append("continue"); opt_label.to_tokens(tokens); } ExprKind::Ret(ref opt_expr) => { tokens.append("return"); opt_expr.to_tokens(tokens); } ExprKind::Mac(ref mac) => mac.to_tokens(tokens), ExprKind::Struct(ref path, ref fields, ref base) => { path.to_tokens(tokens); tokens.append("{"); tokens.append_separated(fields, ","); if let Some(ref base) = *base { if !fields.is_empty() { tokens.append(","); } tokens.append(".."); base.to_tokens(tokens); } tokens.append("}"); } ExprKind::Repeat(ref expr, ref times) => { tokens.append("["); expr.to_tokens(tokens); tokens.append(";"); times.to_tokens(tokens); tokens.append("]"); } ExprKind::Paren(ref expr) => { tokens.append("("); expr.to_tokens(tokens); tokens.append(")"); } ExprKind::Try(ref expr) => { expr.to_tokens(tokens); tokens.append("?"); } } } } impl ToTokens for FieldValue { fn to_tokens(&self, tokens: &mut Tokens) { self.ident.to_tokens(tokens); if !self.is_shorthand { tokens.append(":"); self.expr.to_tokens(tokens); } } } impl ToTokens for Arm { fn to_tokens(&self, tokens: &mut Tokens) { for attr in &self.attrs { attr.to_tokens(tokens); } tokens.append_separated(&self.pats, "|"); if let Some(ref guard) = self.guard { tokens.append("if"); guard.to_tokens(tokens); } tokens.append("=>"); self.body.to_tokens(tokens); match self.body.node { ExprKind::Block(Unsafety::Normal, _) => { // no comma } _ => tokens.append(","), } } } impl ToTokens for Pat { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Pat::Wild => tokens.append("_"), Pat::Ident(mode, ref ident, ref subpat) => { mode.to_tokens(tokens); ident.to_tokens(tokens); if let Some(ref subpat) = *subpat { tokens.append("@"); subpat.to_tokens(tokens); } } Pat::Struct(ref path, ref fields, dots) => { path.to_tokens(tokens); tokens.append("{"); tokens.append_separated(fields, ","); if dots { if !fields.is_empty() { tokens.append(","); } tokens.append(".."); } tokens.append("}"); } Pat::TupleStruct(ref path, ref pats, dotpos) => { path.to_tokens(tokens); tokens.append("("); match dotpos { Some(pos) => { if pos > 0 { tokens.append_separated(&pats[..pos], ","); tokens.append(","); } tokens.append(".."); if pos < pats.len() { tokens.append(","); tokens.append_separated(&pats[pos..], ","); } } None => tokens.append_separated(pats, ","), } tokens.append(")"); } Pat::Path(None, ref path) => path.to_tokens(tokens), Pat::Path(Some(ref qself), ref path) => { tokens.append("<"); qself.ty.to_tokens(tokens); if qself.position > 0 { tokens.append("as"); for (i, segment) in path.segments .iter() .take(qself.position) .enumerate() { if i > 0 || path.global { tokens.append("::"); } segment.to_tokens(tokens); } } tokens.append(">"); for segment in path.segments.iter().skip(qself.position) { tokens.append("::"); segment.to_tokens(tokens); } } Pat::Tuple(ref pats, dotpos) => { tokens.append("("); match dotpos { Some(pos) => { if pos > 0 { tokens.append_separated(&pats[..pos], ","); tokens.append(","); } tokens.append(".."); if pos < pats.len() { tokens.append(","); tokens.append_separated(&pats[pos..], ","); } } None => { tokens.append_separated(pats, ","); if pats.len() == 1 { tokens.append(","); } } } tokens.append(")"); } Pat::Box(ref inner) => { tokens.append("box"); inner.to_tokens(tokens); } Pat::Ref(ref target, mutability) => { tokens.append("&"); mutability.to_tokens(tokens); target.to_tokens(tokens); } Pat::Lit(ref lit) => lit.to_tokens(tokens), Pat::Range(ref lo, ref hi) => { lo.to_tokens(tokens); tokens.append("..."); hi.to_tokens(tokens); } Pat::Slice(ref before, ref rest, ref after) => { tokens.append("["); tokens.append_separated(before, ","); if let Some(ref rest) = *rest { if !before.is_empty() { tokens.append(","); } if **rest != Pat::Wild { rest.to_tokens(tokens); } tokens.append(".."); if !after.is_empty() { tokens.append(","); } tokens.append_separated(after, ","); } tokens.append("]"); } Pat::Mac(ref mac) => mac.to_tokens(tokens), } } } impl ToTokens for FieldPat { fn to_tokens(&self, tokens: &mut Tokens) { if !self.is_shorthand { self.ident.to_tokens(tokens); tokens.append(":"); } self.pat.to_tokens(tokens); } } impl ToTokens for BindingMode { fn to_tokens(&self, tokens: &mut Tokens) { match *self { BindingMode::ByRef(Mutability::Immutable) => { tokens.append("ref"); } BindingMode::ByRef(Mutability::Mutable) => { tokens.append("ref"); tokens.append("mut"); } BindingMode::ByValue(Mutability::Immutable) => {} BindingMode::ByValue(Mutability::Mutable) => { tokens.append("mut"); } } } } impl ToTokens for CaptureBy { fn to_tokens(&self, tokens: &mut Tokens) { match *self { CaptureBy::Value => tokens.append("move"), CaptureBy::Ref => { // nothing } } } } impl ToTokens for Block { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append("{"); tokens.append_all(&self.stmts); tokens.append("}"); } } impl ToTokens for Stmt { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Stmt::Local(ref local) => local.to_tokens(tokens), Stmt::Item(ref item) => item.to_tokens(tokens), Stmt::Expr(ref expr) => expr.to_tokens(tokens), Stmt::Semi(ref expr) => { expr.to_tokens(tokens); tokens.append(";"); } Stmt::Mac(ref mac) => { let (ref mac, style, ref attrs) = **mac; tokens.append_all(attrs.outer()); mac.to_tokens(tokens); match style { MacStmtStyle::Semicolon => tokens.append(";"), MacStmtStyle::Braces | MacStmtStyle::NoBraces => { // no semicolon } } } } } } impl ToTokens for Local { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); tokens.append("let"); self.pat.to_tokens(tokens); if let Some(ref ty) = self.ty { tokens.append(":"); ty.to_tokens(tokens); } if let Some(ref init) = self.init { tokens.append("="); init.to_tokens(tokens); } tokens.append(";"); } } } cpp_syn-0.12.0/src/fold.rs01006440000765000002400000114520130566610420013553 0ustar0000000000000000// Adapted from libsyntax. //! A Folder represents an AST->AST fold; it accepts an AST piece, //! and returns a piece of the same type. use super::*; use constant; /// AST->AST fold. /// /// Each method of the Folder trait is a hook to be potentially overridden. Each /// method's default implementation recursively visits the substructure of the /// input via the `noop_fold` methods, which perform an "identity fold", that /// is, they return the same structure that they are given (for example the /// `fold_crate` method by default calls `fold::noop_fold_crate`). /// /// If you want to ensure that your code handles every variant explicitly, you /// need to override each method and monitor future changes to `Folder` in case /// a new method with a new default implementation gets introduced. pub trait Folder { // Any additions to this trait should happen in form // of a call to a public `noop_*` function that only calls // out to the folder again, not other `noop_*` functions. // // This is a necessary API workaround to the problem of not // being able to call out to the super default method // in an overridden default method. fn fold_ident(&mut self, _ident: Ident) -> Ident { noop_fold_ident(self, _ident) } fn fold_derive_input(&mut self, derive_input: DeriveInput) -> DeriveInput { noop_fold_derive_input(self, derive_input) } fn fold_ty(&mut self, ty: Ty) -> Ty { noop_fold_ty(self, ty) } fn fold_generics(&mut self, generics: Generics) -> Generics { noop_fold_generics(self, generics) } fn fold_ty_param_bound(&mut self, bound: TyParamBound) -> TyParamBound { noop_fold_ty_param_bound(self, bound) } fn fold_poly_trait_ref(&mut self, trait_ref: PolyTraitRef) -> PolyTraitRef { noop_fold_poly_trait_ref(self, trait_ref) } fn fold_variant_data(&mut self, data: VariantData) -> VariantData { noop_fold_variant_data(self, data) } fn fold_field(&mut self, field: Field) -> Field { noop_fold_field(self, field) } fn fold_variant(&mut self, variant: Variant) -> Variant { noop_fold_variant(self, variant) } fn fold_lifetime(&mut self, _lifetime: Lifetime) -> Lifetime { noop_fold_lifetime(self, _lifetime) } fn fold_lifetime_def(&mut self, lifetime: LifetimeDef) -> LifetimeDef { noop_fold_lifetime_def(self, lifetime) } fn fold_path(&mut self, path: Path) -> Path { noop_fold_path(self, path) } fn fold_path_segment(&mut self, path_segment: PathSegment) -> PathSegment { noop_fold_path_segment(self, path_segment) } fn fold_path_parameters(&mut self, path_parameters: PathParameters) -> PathParameters { noop_fold_path_parameters(self, path_parameters) } fn fold_assoc_type_binding(&mut self, type_binding: TypeBinding) -> TypeBinding { noop_fold_assoc_type_binding(self, type_binding) } fn fold_attribute(&mut self, _attr: Attribute) -> Attribute { noop_fold_attribute(self, _attr) } fn fold_fn_ret_ty(&mut self, ret_ty: FunctionRetTy) -> FunctionRetTy { noop_fold_fn_ret_ty(self, ret_ty) } fn fold_const_expr(&mut self, expr: ConstExpr) -> ConstExpr { noop_fold_const_expr(self, expr) } fn fold_lit(&mut self, _lit: Lit) -> Lit { noop_fold_lit(self, _lit) } fn fold_meta_item(&mut self, mitem: MetaItem) -> MetaItem { noop_fold_meta_item(self, mitem) } fn fold_mac(&mut self, mac: Mac) -> Mac { noop_fold_mac(self, mac) } fn fold_tt(&mut self, tt: TokenTree) -> TokenTree { noop_fold_tt(self, tt) } fn fold_span(&mut self, span: Span) -> Span { noop_fold_span(self, span) } #[cfg(feature = "full")] fn fold_crate(&mut self, _crate: Crate) -> Crate { noop_fold_crate(self, _crate) } #[cfg(feature = "full")] fn fold_item(&mut self, item: Item) -> Item { noop_fold_item(self, item) } #[cfg(feature = "full")] fn fold_expr(&mut self, expr: Expr) -> Expr { noop_fold_expr(self, expr) } #[cfg(feature = "full")] fn fold_foreign_item(&mut self, foreign_item: ForeignItem) -> ForeignItem { noop_fold_foreign_item(self, foreign_item) } #[cfg(feature = "full")] fn fold_pat(&mut self, pat: Pat) -> Pat { noop_fold_pat(self, pat) } #[cfg(feature = "full")] fn fold_fn_decl(&mut self, fn_decl: FnDecl) -> FnDecl { noop_fold_fn_decl(self, fn_decl) } #[cfg(feature = "full")] fn fold_trait_item(&mut self, trait_item: TraitItem) -> TraitItem { noop_fold_trait_item(self, trait_item) } #[cfg(feature = "full")] fn fold_impl_item(&mut self, impl_item: ImplItem) -> ImplItem { noop_fold_impl_item(self, impl_item) } #[cfg(feature = "full")] fn fold_method_sig(&mut self, method_sig: MethodSig) -> MethodSig { noop_fold_method_sig(self, method_sig) } #[cfg(feature = "full")] fn fold_stmt(&mut self, stmt: Stmt) -> Stmt { noop_fold_stmt(self, stmt) } #[cfg(feature = "full")] fn fold_block(&mut self, block: Block) -> Block { noop_fold_block(self, block) } #[cfg(feature = "full")] fn fold_local(&mut self, local: Local) -> Local { noop_fold_local(self, local) } #[cfg(feature = "full")] fn fold_view_path(&mut self, view_path: ViewPath) -> ViewPath { noop_fold_view_path(self, view_path) } } trait LiftOnce { type Output; fn lift(self, f: F) -> Self::Output where F: FnOnce(T) -> U; } impl LiftOnce for Box { type Output = Box; fn lift(self, f: F) -> Box where F: FnOnce(T) -> U { Box::new(f(*self)) } } trait LiftMut { type Output; fn lift(self, f: F) -> Self::Output where F: FnMut(T) -> U; } impl LiftMut for Vec { type Output = Vec; fn lift(self, f: F) -> Vec where F: FnMut(T) -> U { self.into_iter().map(f).collect() } } pub fn noop_fold_ident(_: &mut F, _ident: Ident) -> Ident { _ident } pub fn noop_fold_derive_input(folder: &mut F, DeriveInput{ ident, vis, attrs, generics, body, span }: DeriveInput) -> DeriveInput { use Body::*; DeriveInput { ident: folder.fold_ident(ident), vis: noop_fold_vis(folder, vis), attrs: attrs.lift(|a| folder.fold_attribute(a)), generics: folder.fold_generics(generics), body: match body { Enum(variants) => Enum(variants.lift(|v| folder.fold_variant(v))), Struct(variant_data) => Struct(folder.fold_variant_data(variant_data)), }, span: folder.fold_span(span), } } pub fn noop_fold_ty(folder: &mut F, ty: Ty) -> Ty { use Ty::*; match ty { Slice(inner) => Slice(inner.lift(|v| folder.fold_ty(v))), Paren(inner) => Paren(inner.lift(|v| folder.fold_ty(v))), Ptr(mutable_type) => { let mutable_type_ = *mutable_type; let MutTy { ty, mutability }: MutTy = mutable_type_; Ptr(Box::new(MutTy { ty: folder.fold_ty(ty), mutability: mutability, })) } Rptr(opt_lifetime, mutable_type) => { let mutable_type_ = *mutable_type; let MutTy { ty, mutability }: MutTy = mutable_type_; Rptr(opt_lifetime.map(|l| folder.fold_lifetime(l)), Box::new(MutTy { ty: folder.fold_ty(ty), mutability: mutability, })) } Never => Never, Infer => Infer, Tup(tuple_element_types) => Tup(tuple_element_types.lift(|x| folder.fold_ty(x))), BareFn(bare_fn) => { let bf_ = *bare_fn; let BareFnTy { unsafety, abi, lifetimes, inputs, output, variadic } = bf_; BareFn(Box::new(BareFnTy { unsafety: unsafety, abi: abi, lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)), inputs: inputs.lift(|v| { BareFnArg { name: v.name.map(|n| folder.fold_ident(n)), ty: folder.fold_ty(v.ty), } }), output: folder.fold_fn_ret_ty(output), variadic: variadic, })) } Path(maybe_qself, path) => { Path(maybe_qself.map(|v| noop_fold_qself(folder, v)), folder.fold_path(path)) } Array(inner, len) => { Array({ inner.lift(|v| folder.fold_ty(v)) }, folder.fold_const_expr(len)) } TraitObject(bounds) => TraitObject(bounds.lift(|v| folder.fold_ty_param_bound(v))), ImplTrait(bounds) => ImplTrait(bounds.lift(|v| folder.fold_ty_param_bound(v))), Mac(mac) => Mac(folder.fold_mac(mac)), } } fn noop_fold_qself(folder: &mut F, QSelf { ty, position }: QSelf) -> QSelf { QSelf { ty: Box::new(folder.fold_ty(*(ty))), position: position, } } pub fn noop_fold_generics(folder: &mut F, Generics { lifetimes, ty_params, where_clause }: Generics) -> Generics { use WherePredicate::*; Generics { lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)), ty_params: ty_params.lift(|ty| { TyParam { attrs: ty.attrs.lift(|a| folder.fold_attribute(a)), ident: folder.fold_ident(ty.ident), bounds: ty.bounds .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)), default: ty.default.map(|v| folder.fold_ty(v)), } }), where_clause: WhereClause { predicates: where_clause.predicates .lift(|p| match p { BoundPredicate(bound_predicate) => { BoundPredicate(WhereBoundPredicate { bound_lifetimes: bound_predicate.bound_lifetimes .lift(|l| folder.fold_lifetime_def(l)), bounded_ty: folder.fold_ty(bound_predicate.bounded_ty), bounds: bound_predicate.bounds .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)), }) } RegionPredicate(region_predicate) => { RegionPredicate(WhereRegionPredicate { lifetime: folder.fold_lifetime(region_predicate.lifetime), bounds: region_predicate.bounds .lift(|b| folder.fold_lifetime(b)), }) } EqPredicate(eq_predicate) => { EqPredicate(WhereEqPredicate { lhs_ty: folder.fold_ty(eq_predicate.lhs_ty), rhs_ty: folder.fold_ty(eq_predicate.rhs_ty), }) } }), }, } } pub fn noop_fold_ty_param_bound(folder: &mut F, bound: TyParamBound) -> TyParamBound { use TyParamBound::*; match bound { Trait(ty, modifier) => Trait(folder.fold_poly_trait_ref(ty), modifier), Region(lifetime) => Region(folder.fold_lifetime(lifetime)), } } pub fn noop_fold_poly_trait_ref(folder: &mut F, trait_ref: PolyTraitRef) -> PolyTraitRef { PolyTraitRef { bound_lifetimes: trait_ref.bound_lifetimes .lift(|bl| folder.fold_lifetime_def(bl)), trait_ref: folder.fold_path(trait_ref.trait_ref), } } pub fn noop_fold_variant_data(folder: &mut F, data: VariantData) -> VariantData { use VariantData::*; match data { Struct(fields) => Struct(fields.lift(|f| folder.fold_field(f))), Tuple(fields) => Tuple(fields.lift(|f| folder.fold_field(f))), Unit => Unit, } } pub fn noop_fold_field(folder: &mut F, field: Field) -> Field { Field { ident: field.ident.map(|i| folder.fold_ident(i)), vis: noop_fold_vis(folder, field.vis), attrs: field.attrs.lift(|a| folder.fold_attribute(a)), ty: folder.fold_ty(field.ty), } } pub fn noop_fold_variant(folder: &mut F, Variant { ident, attrs, data, discriminant }: Variant) -> Variant { Variant { ident: folder.fold_ident(ident), attrs: attrs.lift(|v| folder.fold_attribute(v)), data: folder.fold_variant_data(data), discriminant: discriminant.map(|ce| folder.fold_const_expr(ce)), } } pub fn noop_fold_lifetime(folder: &mut F, _lifetime: Lifetime) -> Lifetime { Lifetime { ident: folder.fold_ident(_lifetime.ident) } } pub fn noop_fold_lifetime_def(folder: &mut F, LifetimeDef { attrs, lifetime, bounds }: LifetimeDef) -> LifetimeDef { LifetimeDef { attrs: attrs.lift(|x| folder.fold_attribute(x)), lifetime: folder.fold_lifetime(lifetime), bounds: bounds.lift(|l| folder.fold_lifetime(l)), } } pub fn noop_fold_path(folder: &mut F, Path { global, segments }: Path) -> Path { Path { global: global, segments: segments.lift(|s| folder.fold_path_segment(s)), } } pub fn noop_fold_path_segment(folder: &mut F, PathSegment { ident, parameters }: PathSegment) -> PathSegment { PathSegment { ident: folder.fold_ident(ident), parameters: folder.fold_path_parameters(parameters), } } pub fn noop_fold_path_parameters(folder: &mut F, path_parameters: PathParameters) -> PathParameters { use PathParameters::*; match path_parameters { AngleBracketed(d) => { let AngleBracketedParameterData { lifetimes, types, bindings } = d; AngleBracketed(AngleBracketedParameterData { lifetimes: lifetimes.into_iter().map(|l| folder.fold_lifetime(l)).collect(), types: types.lift(|ty| folder.fold_ty(ty)), bindings: bindings.lift(|tb| folder.fold_assoc_type_binding(tb)), }) } Parenthesized(d) => { let ParenthesizedParameterData { inputs, output } = d; Parenthesized(ParenthesizedParameterData { inputs: inputs.lift(|i| folder.fold_ty(i)), output: output.map(|v| folder.fold_ty(v)), }) } } } pub fn noop_fold_assoc_type_binding(folder: &mut F, TypeBinding { ident, ty }: TypeBinding) -> TypeBinding { TypeBinding { ident: folder.fold_ident(ident), ty: folder.fold_ty(ty), } } pub fn noop_fold_attribute(folder: &mut F, attr: Attribute) -> Attribute { Attribute { style: attr.style, value: folder.fold_meta_item(attr.value), is_sugared_doc: attr.is_sugared_doc, span: folder.fold_span(attr.span), } } pub fn noop_fold_fn_ret_ty(folder: &mut F, ret_ty: FunctionRetTy) -> FunctionRetTy { use FunctionRetTy::*; match ret_ty { Default => Default, Ty(ty) => Ty(folder.fold_ty(ty)), } } pub fn noop_fold_const_expr(folder: &mut F, expr: ConstExpr) -> ConstExpr { use ConstExpr::*; match expr { Call(f, args) => { Call(f.lift(|e| folder.fold_const_expr(e)), args.lift(|v| folder.fold_const_expr(v))) } Binary(op, lhs, rhs) => { Binary(op, lhs.lift(|e| folder.fold_const_expr(e)), rhs.lift(|e| folder.fold_const_expr(e))) } Unary(op, e) => Unary(op, e.lift(|e| folder.fold_const_expr(e))), Lit(l) => Lit(folder.fold_lit(l)), Cast(e, ty) => { Cast(e.lift(|e| folder.fold_const_expr(e)), ty.lift(|v| folder.fold_ty(v))) } Path(p) => Path(folder.fold_path(p)), Index(o, i) => { Index(o.lift(|e| folder.fold_const_expr(e)), i.lift(|e| folder.fold_const_expr(e))) } Paren(no_op) => Paren(no_op.lift(|e| folder.fold_const_expr(e))), Other(e) => Other(noop_fold_other_const_expr(folder, e)), } } #[cfg(feature = "full")] fn noop_fold_other_const_expr(folder: &mut F, e: Expr) -> Expr { folder.fold_expr(e) } #[cfg(not(feature = "full"))] fn noop_fold_other_const_expr(_: &mut F, e: constant::Other) -> constant::Other { e } pub fn noop_fold_lit(folder: &mut F, lit: Lit) -> Lit { Lit { node: lit.node, span: folder.fold_span(lit.span), } } pub fn noop_fold_tt(folder: &mut F, tt: TokenTree) -> TokenTree { use TokenTree::*; use Token::*; match tt { Token(token, span) => { Token(match token { Literal(lit) => Literal(folder.fold_lit(lit)), Ident(ident) => Ident(folder.fold_ident(ident)), Lifetime(ident) => Lifetime(folder.fold_ident(ident)), x => x, }, folder.fold_span(span)) } Delimited(super::Delimited { delim, tts }, span) => { Delimited(super::Delimited { delim: delim, tts: tts.lift(|v| folder.fold_tt(v)), }, folder.fold_span(span)) } } } pub fn noop_fold_meta_item(folder: &mut F, mitem: MetaItem) -> MetaItem { match mitem { MetaItem::Word(id) => MetaItem::Word(folder.fold_ident(id)), MetaItem::List(id, nested) => { let nested = nested.lift(|n| noop_fold_nested_meta_item(folder, n)); MetaItem::List(folder.fold_ident(id), nested) } MetaItem::NameValue(id, lit) => MetaItem::NameValue(folder.fold_ident(id), folder.fold_lit(lit)), } } pub fn noop_fold_nested_meta_item(folder: &mut F, nested_mitem: NestedMetaItem) -> NestedMetaItem { match nested_mitem { NestedMetaItem::MetaItem(mitem) => NestedMetaItem::MetaItem(folder.fold_meta_item(mitem)), NestedMetaItem::Literal(lit) => NestedMetaItem::Literal(folder.fold_lit(lit)), } } pub fn noop_fold_mac(folder: &mut F, Mac { path, tts }: Mac) -> Mac { Mac { path: folder.fold_path(path), tts: tts.lift(|tt| folder.fold_tt(tt)), } } pub fn noop_fold_span(_: &mut F, s: Span) -> Span { s } #[cfg(feature = "full")] pub fn noop_fold_crate(folder: &mut F, Crate { shebang, attrs, items }: Crate) -> Crate { Crate { shebang: shebang, attrs: attrs.lift(|a| folder.fold_attribute(a)), items: items.lift(|i| folder.fold_item(i)), } } #[cfg(feature = "full")] pub fn noop_fold_block(folder: &mut F, block: Block) -> Block { Block { stmts: block.stmts.lift(|s| folder.fold_stmt(s)) } } fn noop_fold_vis(folder: &mut F, vis: Visibility) -> Visibility { use Visibility::*; match vis { Crate => Crate, Inherited => Inherited, Public => Public, Restricted(path) => Restricted(path.lift(|p| folder.fold_path(p))), } } #[cfg(feature = "full")] pub fn noop_fold_item(folder: &mut F, Item { ident, vis, attrs, node, span }: Item) -> Item { use ItemKind::*; Item { ident: folder.fold_ident(ident.clone()), vis: noop_fold_vis(folder, vis), attrs: attrs.lift(|a| folder.fold_attribute(a)), node: match node { ExternCrate(name) => ExternCrate(name.map(|i| folder.fold_ident(i))), Use(view_path) => Use(Box::new(folder.fold_view_path(*view_path))), Static(ty, mutability, expr) => { Static(Box::new(folder.fold_ty(*ty)), mutability, expr.lift(|e| folder.fold_expr(e))) } Const(ty, expr) => { Const(ty.lift(|ty| folder.fold_ty(ty)), expr.lift(|e| folder.fold_expr(e))) } Fn(fn_decl, unsafety, constness, abi, generics, block) => { Fn(fn_decl.lift(|v| folder.fold_fn_decl(v)), unsafety, constness, abi, folder.fold_generics(generics), block.lift(|v| folder.fold_block(v))) } Mod(items) => Mod(items.map(|items| items.lift(|i| folder.fold_item(i)))), ForeignMod(super::ForeignMod { abi, items }) => { ForeignMod(super::ForeignMod { abi: abi, items: items.lift(|foreign_item| folder.fold_foreign_item(foreign_item)), }) } Ty(ty, generics) => { Ty(ty.lift(|ty| folder.fold_ty(ty)), folder.fold_generics(generics)) } Enum(variants, generics) => { Enum(variants.lift(|v| folder.fold_variant(v)), folder.fold_generics(generics)) } Struct(variant_data, generics) => { Struct(folder.fold_variant_data(variant_data), folder.fold_generics(generics)) } Union(variant_data, generics) => { Union(folder.fold_variant_data(variant_data), folder.fold_generics(generics)) } Trait(unsafety, generics, typbs, trait_items) => { Trait(unsafety, folder.fold_generics(generics), typbs.lift(|typb| folder.fold_ty_param_bound(typb)), trait_items.lift(|ti| folder.fold_trait_item(ti))) } DefaultImpl(unsafety, path) => DefaultImpl(unsafety, folder.fold_path(path)), Impl(unsafety, impl_polarity, generics, path, ty, impl_items) => { Impl(unsafety, impl_polarity, folder.fold_generics(generics), path.map(|p| folder.fold_path(p)), ty.lift(|ty| folder.fold_ty(ty)), impl_items.lift(|i| folder.fold_impl_item(i))) } Mac(mac) => Mac(folder.fold_mac(mac)), }, span: folder.fold_span(span), } } #[cfg(feature = "full")] pub fn noop_fold_expr(folder: &mut F, Expr { node, attrs, span }: Expr) -> Expr { use ExprKind::*; Expr { node: match node { ExprKind::Box(e) => ExprKind::Box(e.lift(|e| folder.fold_expr(e))), InPlace(place, value) => { InPlace(place.lift(|e| folder.fold_expr(e)), value.lift(|e| folder.fold_expr(e))) } Array(array) => Array(array.lift(|e| folder.fold_expr(e))), Call(function, args) => { Call(function.lift(|e| folder.fold_expr(e)), args.lift(|e| folder.fold_expr(e))) } MethodCall(method, tys, args) => { MethodCall(folder.fold_ident(method), tys.lift(|t| folder.fold_ty(t)), args.lift(|e| folder.fold_expr(e))) } Tup(args) => Tup(args.lift(|e| folder.fold_expr(e))), Binary(bop, lhs, rhs) => { Binary(bop, lhs.lift(|e| folder.fold_expr(e)), rhs.lift(|e| folder.fold_expr(e))) } Unary(uop, e) => Unary(uop, e.lift(|e| folder.fold_expr(e))), Lit(lit) => Lit(folder.fold_lit(lit)), Cast(e, ty) => { Cast(e.lift(|e| folder.fold_expr(e)), ty.lift(|t| folder.fold_ty(t))) } Type(e, ty) => { Type(e.lift(|e| folder.fold_expr(e)), ty.lift(|t| folder.fold_ty(t))) } If(e, if_block, else_block) => { If(e.lift(|e| folder.fold_expr(e)), folder.fold_block(if_block), else_block.map(|v| v.lift(|e| folder.fold_expr(e)))) } IfLet(pat, expr, block, else_block) => { IfLet(pat.lift(|p| folder.fold_pat(p)), expr.lift(|e| folder.fold_expr(e)), folder.fold_block(block), else_block.map(|v| v.lift(|e| folder.fold_expr(e)))) } While(e, block, label) => { While(e.lift(|e| folder.fold_expr(e)), folder.fold_block(block), label.map(|i| folder.fold_ident(i))) } WhileLet(pat, expr, block, label) => { WhileLet(pat.lift(|p| folder.fold_pat(p)), expr.lift(|e| folder.fold_expr(e)), folder.fold_block(block), label.map(|i| folder.fold_ident(i))) } ForLoop(pat, expr, block, label) => { ForLoop(pat.lift(|p| folder.fold_pat(p)), expr.lift(|e| folder.fold_expr(e)), folder.fold_block(block), label.map(|i| folder.fold_ident(i))) } Loop(block, label) => { Loop(folder.fold_block(block), label.map(|i| folder.fold_ident(i))) } Match(e, arms) => { Match(e.lift(|e| folder.fold_expr(e)), arms.lift(|Arm { attrs, pats, guard, body }: Arm| { Arm { attrs: attrs.lift(|a| folder.fold_attribute(a)), pats: pats.lift(|p| folder.fold_pat(p)), guard: guard.map(|v| v.lift(|e| folder.fold_expr(e))), body: body.lift(|e| folder.fold_expr(e)), } })) } Closure(capture_by, fn_decl, expr) => { Closure(capture_by, fn_decl.lift(|v| folder.fold_fn_decl(v)), expr.lift(|e| folder.fold_expr(e))) } Block(unsafety, block) => Block(unsafety, folder.fold_block(block)), Assign(lhs, rhs) => { Assign(lhs.lift(|e| folder.fold_expr(e)), rhs.lift(|e| folder.fold_expr(e))) } AssignOp(bop, lhs, rhs) => { AssignOp(bop, lhs.lift(|e| folder.fold_expr(e)), rhs.lift(|e| folder.fold_expr(e))) } Field(expr, name) => Field(expr.lift(|e| folder.fold_expr(e)), folder.fold_ident(name)), TupField(expr, index) => TupField(expr.lift(|e| folder.fold_expr(e)), index), Index(expr, index) => { Index(expr.lift(|e| folder.fold_expr(e)), index.lift(|e| folder.fold_expr(e))) } Range(lhs, rhs, limits) => { Range(lhs.map(|v| v.lift(|e| folder.fold_expr(e))), rhs.map(|v| v.lift(|e| folder.fold_expr(e))), limits) } Path(qself, path) => { Path(qself.map(|v| noop_fold_qself(folder, v)), folder.fold_path(path)) } AddrOf(mutability, expr) => AddrOf(mutability, expr.lift(|e| folder.fold_expr(e))), Break(label, expr) => { Break(label.map(|i| folder.fold_ident(i)), expr.map(|v| v.lift(|e| folder.fold_expr(e)))) } Continue(label) => Continue(label.map(|i| folder.fold_ident(i))), Ret(expr) => Ret(expr.map(|v| v.lift(|e| folder.fold_expr(e)))), ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)), Struct(path, fields, expr) => { Struct(folder.fold_path(path), fields.lift(|FieldValue { ident, expr, is_shorthand, attrs }: FieldValue| { FieldValue { ident: folder.fold_ident(ident), expr: folder.fold_expr(expr), is_shorthand: is_shorthand, attrs: attrs.lift(|v| folder.fold_attribute(v)), } }), expr.map(|v| v.lift(|e| folder.fold_expr(e)))) } Repeat(element, number) => { Repeat(element.lift(|e| folder.fold_expr(e)), number.lift(|e| folder.fold_expr(e))) } Paren(expr) => Paren(expr.lift(|e| folder.fold_expr(e))), Try(expr) => Try(expr.lift(|e| folder.fold_expr(e))), }, attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(), span: folder.fold_span(span), } } #[cfg(feature = "full")] pub fn noop_fold_foreign_item(folder: &mut F, ForeignItem { ident, attrs, node, vis, span }: ForeignItem) -> ForeignItem { ForeignItem { ident: folder.fold_ident(ident), attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(), node: match node { ForeignItemKind::Fn(fn_dcl, generics) => { ForeignItemKind::Fn(fn_dcl.lift(|v| folder.fold_fn_decl(v)), folder.fold_generics(generics)) } ForeignItemKind::Static(ty, mutability) => { ForeignItemKind::Static(ty.lift(|v| folder.fold_ty(v)), mutability) } }, vis: noop_fold_vis(folder, vis), span: folder.fold_span(span), } } #[cfg(feature = "full")] pub fn noop_fold_pat(folder: &mut F, pat: Pat) -> Pat { use Pat::*; match pat { Wild => Wild, Ident(binding_mode, ident, pat) => { Ident(binding_mode, folder.fold_ident(ident), pat.map(|p| p.lift(|p| folder.fold_pat(p)))) } Struct(path, field_patterns, dots) => { Struct(folder.fold_path(path), field_patterns.lift(|FieldPat { ident, pat, is_shorthand, attrs }: FieldPat| { FieldPat { ident: folder.fold_ident(ident), pat: pat.lift(|p| folder.fold_pat(p)), is_shorthand: is_shorthand, attrs: attrs.lift(|a| folder.fold_attribute(a)), } }), dots) } TupleStruct(path, pats, len) => { TupleStruct(folder.fold_path(path), pats.lift(|p| folder.fold_pat(p)), len) } Path(qself, path) => { Path(qself.map(|v| noop_fold_qself(folder, v)), folder.fold_path(path)) } Tuple(pats, len) => Tuple(pats.lift(|p| folder.fold_pat(p)), len), Box(b) => Box(b.lift(|p| folder.fold_pat(p))), Ref(b, mutability) => Ref(b.lift(|p| folder.fold_pat(p)), mutability), Lit(expr) => Lit(expr.lift(|e| folder.fold_expr(e))), Range(l, r) => { Range(l.lift(|e| folder.fold_expr(e)), r.lift(|e| folder.fold_expr(e))) } Slice(lefts, pat, rights) => { Slice(lefts.lift(|p| folder.fold_pat(p)), pat.map(|v| v.lift(|p| folder.fold_pat(p))), rights.lift(|p| folder.fold_pat(p))) } Mac(mac) => Mac(folder.fold_mac(mac)), } } #[cfg(feature = "full")] pub fn noop_fold_fn_decl(folder: &mut F, FnDecl { inputs, output, variadic }: FnDecl) -> FnDecl { FnDecl { inputs: inputs.lift(|a| { use FnArg::*; match a { SelfRef(lifetime, mutability) => { SelfRef(lifetime.map(|v| folder.fold_lifetime(v)), mutability) } SelfValue(mutability) => SelfValue(mutability), Captured(pat, ty) => Captured(folder.fold_pat(pat), folder.fold_ty(ty)), Ignored(ty) => Ignored(folder.fold_ty(ty)), } }), output: folder.fold_fn_ret_ty(output), variadic: variadic, } } #[cfg(feature = "full")] pub fn noop_fold_trait_item(folder: &mut F, TraitItem { ident, attrs, node, span }: TraitItem) -> TraitItem { use TraitItemKind::*; TraitItem { ident: folder.fold_ident(ident), attrs: attrs.lift(|v| folder.fold_attribute(v)), node: match node { Const(ty, expr) => Const(folder.fold_ty(ty), expr.map(|v| folder.fold_expr(v))), Method(sig, block) => { Method(folder.fold_method_sig(sig), block.map(|v| folder.fold_block(v))) } Type(ty_pbs, ty) => { Type(ty_pbs.lift(|v| folder.fold_ty_param_bound(v)), ty.map(|v| folder.fold_ty(v))) } Macro(mac) => Macro(folder.fold_mac(mac)), }, span: folder.fold_span(span), } } #[cfg(feature = "full")] pub fn noop_fold_impl_item(folder: &mut F, ImplItem { ident, vis, defaultness, attrs, node, span }: ImplItem) -> ImplItem { use ImplItemKind::*; ImplItem { ident: folder.fold_ident(ident), vis: noop_fold_vis(folder, vis), defaultness: defaultness, attrs: attrs.lift(|v| folder.fold_attribute(v)), node: match node { Const(ty, expr) => Const(folder.fold_ty(ty), folder.fold_expr(expr)), Method(sig, block) => Method(folder.fold_method_sig(sig), folder.fold_block(block)), Type(ty) => Type(folder.fold_ty(ty)), Macro(mac) => Macro(folder.fold_mac(mac)), }, span: folder.fold_span(span), } } #[cfg(feature = "full")] pub fn noop_fold_method_sig(folder: &mut F, MethodSig{unsafety, constness, abi, decl, generics}:MethodSig) -> MethodSig { MethodSig { unsafety: unsafety, constness: constness, abi: abi, decl: folder.fold_fn_decl(decl), generics: folder.fold_generics(generics), } } #[cfg(feature = "full")] pub fn noop_fold_stmt(folder: &mut F, stmt: Stmt) -> Stmt { use Stmt::*; match stmt { Local(local) => Local(local.lift(|l| folder.fold_local(l))), Item(item) => Item(item.lift(|v| folder.fold_item(v))), Expr(expr) => Expr(expr.lift(|v| folder.fold_expr(v))), Semi(expr) => Semi(expr.lift(|v| folder.fold_expr(v))), Mac(mac_stmt) => { Mac(mac_stmt.lift(|(mac, style, attrs)| { (folder.fold_mac(mac), style, attrs.lift(|a| folder.fold_attribute(a))) })) } } } #[cfg(feature = "full")] pub fn noop_fold_local(folder: &mut F, Local { pat, ty, init, attrs }: Local) -> Local { Local { pat: pat.lift(|v| folder.fold_pat(v)), ty: ty.map(|v| v.lift(|t| folder.fold_ty(t))), init: init.map(|v| v.lift(|e| folder.fold_expr(e))), attrs: attrs.lift(|a| folder.fold_attribute(a)), } } #[cfg(feature = "full")] pub fn noop_fold_view_path(folder: &mut F, view_path: ViewPath) -> ViewPath { use ViewPath::*; match view_path { Simple(path, ident) => Simple(folder.fold_path(path), ident.map(|i| folder.fold_ident(i))), Glob(path) => Glob(folder.fold_path(path)), List(path, items) => { List(folder.fold_path(path), items.lift(|PathListItem { name, rename }: PathListItem| { PathListItem { name: folder.fold_ident(name), rename: rename.map(|i| folder.fold_ident(i)), } })) } } } cpp_syn-0.12.0/src/generics.rs01006440000765000002400000035501130566610510014427 0ustar0000000000000000use super::*; /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. #[derive(Debug, Clone, Eq, PartialEq, Default, Hash)] pub struct Generics { pub lifetimes: Vec, pub ty_params: Vec, pub where_clause: WhereClause, } #[cfg(feature = "printing")] /// Returned by `Generics::split_for_impl`. #[derive(Debug)] pub struct ImplGenerics<'a>(&'a Generics); #[cfg(feature = "printing")] /// Returned by `Generics::split_for_impl`. #[derive(Debug)] pub struct TyGenerics<'a>(&'a Generics); #[cfg(feature = "printing")] /// Returned by `TyGenerics::as_turbofish`. #[derive(Debug)] pub struct Turbofish<'a>(&'a Generics); #[cfg(feature = "printing")] impl Generics { /// Split a type's generics into the pieces required for impl'ing a trait /// for that type. /// /// ``` /// # extern crate cpp_syn as syn; /// # #[macro_use] /// # extern crate quote; /// # fn main() { /// # let generics: syn::Generics = Default::default(); /// # let name = syn::Ident::new("MyType"); /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); /// quote! { /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { /// // ... /// } /// } /// # ; /// # } /// ``` pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) { (ImplGenerics(self), TyGenerics(self), &self.where_clause) } } #[cfg(feature = "printing")] impl<'a> TyGenerics<'a> { /// Turn a type's generics like `` into a turbofish like `::`. pub fn as_turbofish(&self) -> Turbofish { Turbofish(self.0) } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Lifetime { pub ident: Ident, } impl Lifetime { pub fn new>(t: T) -> Self { let id = Ident::new(t); if !id.as_ref().starts_with('\'') { panic!("lifetime name must start with apostrophe as in \"'a\", \ got {:?}", id.as_ref()); } Lifetime { ident: id } } } /// A lifetime definition, e.g. `'a: 'b+'c+'d` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct LifetimeDef { pub attrs: Vec, pub lifetime: Lifetime, pub bounds: Vec, } impl LifetimeDef { pub fn new>(t: T) -> Self { LifetimeDef { attrs: Vec::new(), lifetime: Lifetime::new(t), bounds: Vec::new(), } } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct TyParam { pub attrs: Vec, pub ident: Ident, pub bounds: Vec, pub default: Option, } /// The AST represents all type param bounds as types. /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects Copy, Send and Sync. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum TyParamBound { Trait(PolyTraitRef, TraitBoundModifier), Region(Lifetime), } /// A modifier on a bound, currently this is only used for `?Sized`, where the /// modifier is `Maybe`. Negative bounds should also be handled here. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum TraitBoundModifier { None, Maybe, } /// A `where` clause in a definition #[derive(Debug, Clone, Eq, PartialEq, Default, Hash)] pub struct WhereClause { pub predicates: Vec, } impl WhereClause { pub fn none() -> Self { WhereClause { predicates: Vec::new() } } } /// A single predicate in a `where` clause #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum WherePredicate { /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c` BoundPredicate(WhereBoundPredicate), /// A lifetime predicate, e.g. `'a: 'b+'c` RegionPredicate(WhereRegionPredicate), /// An equality predicate (unsupported) EqPredicate(WhereEqPredicate), } /// A type bound. /// /// E.g. `for<'c> Foo: Send+Clone+'c` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct WhereBoundPredicate { /// Any lifetimes from a `for` binding pub bound_lifetimes: Vec, /// The type being bounded pub bounded_ty: Ty, /// Trait and lifetime bounds (`Clone+Send+'static`) pub bounds: Vec, } /// A lifetime predicate. /// /// E.g. `'a: 'b+'c` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct WhereRegionPredicate { pub lifetime: Lifetime, pub bounds: Vec, } /// An equality predicate (unsupported). /// /// E.g. `T=int` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct WhereEqPredicate { pub lhs_ty: Ty, pub rhs_ty: Ty, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use attr::parsing::outer_attr; use ident::parsing::ident; use ty::parsing::{ty, poly_trait_ref}; named!(pub generics -> Generics, map!( alt!( do_parse!( punct!("<") >> lifetimes: separated_list!(punct!(","), lifetime_def) >> ty_params: opt_vec!(preceded!( cond!(!lifetimes.is_empty(), punct!(",")), separated_nonempty_list!(punct!(","), ty_param) )) >> cond!(!lifetimes.is_empty() || !ty_params.is_empty(), option!(punct!(","))) >> punct!(">") >> (lifetimes, ty_params) ) | epsilon!() => { |_| (Vec::new(), Vec::new()) } ), |(lifetimes, ty_params)| Generics { lifetimes: lifetimes, ty_params: ty_params, where_clause: Default::default(), } )); named!(pub lifetime -> Lifetime, preceded!( punct!("'"), alt!( map!(ident, |id| Lifetime { ident: format!("'{}", id).into(), }) | map!(keyword!("static"), |_| Lifetime { ident: "'static".into(), }) ) )); named!(pub lifetime_def -> LifetimeDef, do_parse!( attrs: many0!(outer_attr) >> life: lifetime >> bounds: opt_vec!(preceded!( punct!(":"), separated_list!(punct!("+"), lifetime) )) >> (LifetimeDef { attrs: attrs, lifetime: life, bounds: bounds, }) )); named!(pub bound_lifetimes -> Vec, opt_vec!(do_parse!( keyword!("for") >> punct!("<") >> lifetimes: terminated_list!(punct!(","), lifetime_def) >> punct!(">") >> (lifetimes) ))); named!(ty_param -> TyParam, do_parse!( attrs: many0!(outer_attr) >> id: ident >> bounds: opt_vec!(preceded!( punct!(":"), separated_nonempty_list!(punct!("+"), ty_param_bound) )) >> default: option!(preceded!( punct!("="), ty )) >> (TyParam { attrs: attrs, ident: id, bounds: bounds, default: default, }) )); named!(pub ty_param_bound -> TyParamBound, alt!( preceded!(punct!("?"), poly_trait_ref) => { |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe) } | lifetime => { TyParamBound::Region } | poly_trait_ref => { |poly| TyParamBound::Trait(poly, TraitBoundModifier::None) } )); named!(pub where_clause -> WhereClause, alt!( do_parse!( keyword!("where") >> predicates: separated_nonempty_list!(punct!(","), where_predicate) >> option!(punct!(",")) >> (WhereClause { predicates: predicates }) ) | epsilon!() => { |_| Default::default() } )); named!(where_predicate -> WherePredicate, alt!( do_parse!( ident: lifetime >> bounds: opt_vec!(preceded!( punct!(":"), separated_list!(punct!("+"), lifetime) )) >> (WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime: ident, bounds: bounds, })) ) | do_parse!( bound_lifetimes: bound_lifetimes >> bounded_ty: ty >> punct!(":") >> bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >> (WherePredicate::BoundPredicate(WhereBoundPredicate { bound_lifetimes: bound_lifetimes, bounded_ty: bounded_ty, bounds: bounds, })) ) )); } #[cfg(feature = "printing")] mod printing { use super::*; use attr::FilterAttrs; use quote::{Tokens, ToTokens}; impl ToTokens for Generics { fn to_tokens(&self, tokens: &mut Tokens) { let has_lifetimes = !self.lifetimes.is_empty(); let has_ty_params = !self.ty_params.is_empty(); if has_lifetimes || has_ty_params { tokens.append("<"); tokens.append_separated(&self.lifetimes, ","); if has_lifetimes && has_ty_params { tokens.append(","); } tokens.append_separated(&self.ty_params, ","); tokens.append(">"); } } } impl<'a> ToTokens for ImplGenerics<'a> { fn to_tokens(&self, tokens: &mut Tokens) { let has_lifetimes = !self.0.lifetimes.is_empty(); let has_ty_params = !self.0.ty_params.is_empty(); if has_lifetimes || has_ty_params { tokens.append("<"); tokens.append_separated(&self.0.lifetimes, ","); // Leave off the type parameter defaults for (i, ty_param) in self.0.ty_params.iter().enumerate() { if i > 0 || has_lifetimes { tokens.append(","); } tokens.append_all(ty_param.attrs.outer()); ty_param.ident.to_tokens(tokens); if !ty_param.bounds.is_empty() { tokens.append(":"); tokens.append_separated(&ty_param.bounds, "+"); } } tokens.append(">"); } } } impl<'a> ToTokens for TyGenerics<'a> { fn to_tokens(&self, tokens: &mut Tokens) { let has_lifetimes = !self.0.lifetimes.is_empty(); let has_ty_params = !self.0.ty_params.is_empty(); if has_lifetimes || has_ty_params { tokens.append("<"); // Leave off the lifetime bounds and attributes let lifetimes = self.0.lifetimes.iter().map(|ld| &ld.lifetime); tokens.append_separated(lifetimes, ","); if has_lifetimes && has_ty_params { tokens.append(","); } // Leave off the type parameter bounds, defaults, and attributes let ty_params = self.0.ty_params.iter().map(|tp| &tp.ident); tokens.append_separated(ty_params, ","); tokens.append(">"); } } } impl<'a> ToTokens for Turbofish<'a> { fn to_tokens(&self, tokens: &mut Tokens) { let has_lifetimes = !self.0.lifetimes.is_empty(); let has_ty_params = !self.0.ty_params.is_empty(); if has_lifetimes || has_ty_params { tokens.append("::"); TyGenerics(self.0).to_tokens(tokens); } } } impl ToTokens for Lifetime { fn to_tokens(&self, tokens: &mut Tokens) { self.ident.to_tokens(tokens); } } impl ToTokens for LifetimeDef { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); self.lifetime.to_tokens(tokens); if !self.bounds.is_empty() { tokens.append(":"); tokens.append_separated(&self.bounds, "+"); } } } impl ToTokens for TyParam { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); self.ident.to_tokens(tokens); if !self.bounds.is_empty() { tokens.append(":"); tokens.append_separated(&self.bounds, "+"); } if let Some(ref default) = self.default { tokens.append("="); default.to_tokens(tokens); } } } impl ToTokens for TyParamBound { fn to_tokens(&self, tokens: &mut Tokens) { match *self { TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens), TyParamBound::Trait(ref trait_ref, modifier) => { match modifier { TraitBoundModifier::None => {} TraitBoundModifier::Maybe => tokens.append("?"), } trait_ref.to_tokens(tokens); } } } } impl ToTokens for WhereClause { fn to_tokens(&self, tokens: &mut Tokens) { if !self.predicates.is_empty() { tokens.append("where"); tokens.append_separated(&self.predicates, ","); } } } impl ToTokens for WherePredicate { fn to_tokens(&self, tokens: &mut Tokens) { match *self { WherePredicate::BoundPredicate(ref predicate) => { predicate.to_tokens(tokens); } WherePredicate::RegionPredicate(ref predicate) => { predicate.to_tokens(tokens); } WherePredicate::EqPredicate(ref predicate) => { predicate.to_tokens(tokens); } } } } impl ToTokens for WhereBoundPredicate { fn to_tokens(&self, tokens: &mut Tokens) { if !self.bound_lifetimes.is_empty() { tokens.append("for"); tokens.append("<"); tokens.append_separated(&self.bound_lifetimes, ","); tokens.append(">"); } self.bounded_ty.to_tokens(tokens); if !self.bounds.is_empty() { tokens.append(":"); tokens.append_separated(&self.bounds, "+"); } } } impl ToTokens for WhereRegionPredicate { fn to_tokens(&self, tokens: &mut Tokens) { self.lifetime.to_tokens(tokens); if !self.bounds.is_empty() { tokens.append(":"); tokens.append_separated(&self.bounds, "+"); } } } impl ToTokens for WhereEqPredicate { fn to_tokens(&self, tokens: &mut Tokens) { self.lhs_ty.to_tokens(tokens); tokens.append("="); self.rhs_ty.to_tokens(tokens); } } } cpp_syn-0.12.0/src/ident.rs01006440000765000002400000006702130501226120013721 0ustar0000000000000000use std::borrow::Cow; use std::fmt::{self, Display}; #[derive(Debug, Clone, Eq, Hash)] pub struct Ident(String); impl Ident { pub fn new>(t: T) -> Self { t.into() } } impl<'a> From<&'a str> for Ident { fn from(s: &str) -> Self { Ident(s.to_owned()) } } impl<'a> From> for Ident { fn from(s: Cow<'a, str>) -> Self { Ident(s.into_owned()) } } impl From for Ident { fn from(s: String) -> Self { Ident(s) } } impl From for Ident { fn from(u: usize) -> Self { Ident(u.to_string()) } } impl AsRef for Ident { fn as_ref(&self) -> &str { &self.0 } } impl Display for Ident { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.0.fmt(formatter) } } impl PartialEq for Ident where T: AsRef { fn eq(&self, other: &T) -> bool { self.0 == other.as_ref() } } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use synom::{IResult, ParseState}; use synom::space::skip_whitespace; use unicode_xid::UnicodeXID; pub fn ident(input: ParseState) -> IResult { let (rest, id) = match word(input) { IResult::Done(rest, id) => (rest, id), IResult::Error => return IResult::Error, }; match id.as_ref() { // From https://doc.rust-lang.org/grammar.html#keywords "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" => IResult::Error, _ => IResult::Done(rest, id), } } pub fn word(mut input: ParseState) -> IResult { input = skip_whitespace(input); let mut chars = input.char_indices(); match chars.next() { Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {} _ => return IResult::Error, } while let Some((i, ch)) = chars.next() { if !UnicodeXID::is_xid_continue(ch) { return IResult::Done(input.advance(i), input.until(i).into()); } } IResult::Done(input.finish(), input.rest().into()) } #[cfg(feature = "full")] pub fn wordlike(mut input: ParseState) -> IResult { input = skip_whitespace(input); for (i, ch) in input.char_indices() { if !UnicodeXID::is_xid_start(ch) && !UnicodeXID::is_xid_continue(ch) { return if i == 0 { IResult::Error } else { IResult::Done(input.advance(i), input.until(i).into()) }; } } IResult::Done(input.finish(), input.rest().into()) } } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for Ident { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append(self.as_ref()) } } } cpp_syn-0.12.0/src/item.rs01006440000765000002400000135373130566610420013576 0ustar0000000000000000use super::*; /// An item /// /// The name might be a dummy name in case of anonymous items #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Item { pub ident: Ident, pub vis: Visibility, pub attrs: Vec, pub node: ItemKind, pub span: Span, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ItemKind { /// An`extern crate` item, with optional original crate name. /// /// E.g. `extern crate foo` or `extern crate foo_bar as foo` ExternCrate(Option), /// A use declaration (`use` or `pub use`) item. /// /// E.g. `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;` Use(Box), /// A static item (`static` or `pub static`). /// /// E.g. `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";` Static(Box, Mutability, Box), /// A constant item (`const` or `pub const`). /// /// E.g. `const FOO: i32 = 42;` Const(Box, Box), /// A function declaration (`fn` or `pub fn`). /// /// E.g. `fn foo(bar: usize) -> usize { .. }` Fn(Box, Unsafety, Constness, Option, Generics, Box), /// A module declaration (`mod` or `pub mod`). /// /// E.g. `mod foo;` or `mod foo { .. }` Mod(Option>), /// An external module (`extern` or `pub extern`). /// /// E.g. `extern {}` or `extern "C" {}` ForeignMod(ForeignMod), /// A type alias (`type` or `pub type`). /// /// E.g. `type Foo = Bar;` Ty(Box, Generics), /// An enum definition (`enum` or `pub enum`). /// /// E.g. `enum Foo { C, D }` Enum(Vec, Generics), /// A struct definition (`struct` or `pub struct`). /// /// E.g. `struct Foo { x: A }` Struct(VariantData, Generics), /// A union definition (`union` or `pub union`). /// /// E.g. `union Foo { x: A, y: B }` Union(VariantData, Generics), /// A Trait declaration (`trait` or `pub trait`). /// /// E.g. `trait Foo { .. }` or `trait Foo { .. }` Trait(Unsafety, Generics, Vec, Vec), /// Default trait implementation. /// /// E.g. `impl Trait for .. {}` or `impl Trait for .. {}` DefaultImpl(Unsafety, Path), /// An implementation. /// /// E.g. `impl Foo { .. }` or `impl Trait for Foo { .. }` Impl(Unsafety, ImplPolarity, Generics, Option, // (optional) trait this impl implements Box, // self Vec), /// A macro invocation (which includes macro definition). /// /// E.g. `macro_rules! foo { .. }` or `foo!(..)` Mac(Mac), } impl From for Item { fn from(input: DeriveInput) -> Item { Item { ident: input.ident, vis: input.vis, attrs: input.attrs, node: match input.body { Body::Enum(variants) => ItemKind::Enum(variants, input.generics), Body::Struct(variant_data) => ItemKind::Struct(variant_data, input.generics), }, span: input.span, } } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ViewPath { /// `foo::bar::baz as quux` /// /// or just /// /// `foo::bar::baz` (with `as baz` implicitly on the right) Simple(Path, Option), /// `foo::bar::*` Glob(Path), /// `foo::bar::{a, b, c}` List(Path, Vec), } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct PathListItem { pub name: Ident, /// renamed in list, e.g. `use foo::{bar as baz};` pub rename: Option, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Constness { Const, NotConst, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Defaultness { Default, Final, } /// Foreign module declaration. /// /// E.g. `extern { .. }` or `extern "C" { .. }` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct ForeignMod { pub abi: Abi, pub items: Vec, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct ForeignItem { pub ident: Ident, pub attrs: Vec, pub node: ForeignItemKind, pub vis: Visibility, pub span: Span, } /// An item within an `extern` block #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ForeignItemKind { /// A foreign function Fn(Box, Generics), /// A foreign static item (`static ext: u8`) Static(Box, Mutability), } /// Represents an item declaration within a trait declaration, /// possibly including a default implementation. A trait item is /// either required (meaning it doesn't have an implementation, just a /// signature) or provided (meaning it has a default implementation). #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct TraitItem { pub ident: Ident, pub attrs: Vec, pub node: TraitItemKind, pub span: Span, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum TraitItemKind { Const(Ty, Option), Method(MethodSig, Option), Type(Vec, Option), Macro(Mac), } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum ImplPolarity { /// `impl Trait for Type` Positive, /// `impl !Trait for Type` Negative, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct ImplItem { pub ident: Ident, pub vis: Visibility, pub defaultness: Defaultness, pub attrs: Vec, pub node: ImplItemKind, pub span: Span, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ImplItemKind { Const(Ty, Expr), Method(MethodSig, Block), Type(Ty), Macro(Mac), } /// Represents a method's signature in a trait declaration, /// or in an implementation. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct MethodSig { pub unsafety: Unsafety, pub constness: Constness, pub abi: Option, pub decl: FnDecl, pub generics: Generics, } /// Header (not the body) of a function declaration. /// /// E.g. `fn foo(bar: baz)` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct FnDecl { pub inputs: Vec, pub output: FunctionRetTy, pub variadic: bool, } /// An argument in a function header. /// /// E.g. `bar: usize` as in `fn foo(bar: usize)` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum FnArg { SelfRef(Option, Mutability), SelfValue(Mutability), Captured(Pat, Ty), Ignored(Ty), } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use {Block, DelimToken, FunctionRetTy, Generics, Ident, Mac, Path, TokenTree, VariantData, Visibility}; use attr::parsing::{inner_attr, outer_attr}; use data::parsing::{struct_like_body, visibility}; use expr::parsing::{expr, pat, within_block}; use generics::parsing::{generics, lifetime, ty_param_bound, where_clause}; use ident::parsing::ident; use mac::parsing::delimited; use derive::{Body, DeriveInput}; use derive::parsing::derive_input; use ty::parsing::{abi, mutability, path, ty, unsafety}; named!(pub item -> Item, add_span!(alt!( item_extern_crate | item_use | item_static | item_const | item_fn | item_mod | item_foreign_mod | item_ty | item_struct_or_enum | item_union | item_trait | item_default_impl | item_impl | item_mac ))); named!(pub items -> Vec, many0!(item)); named!(item_mac -> Item, do_parse!( attrs: many0!(outer_attr) >> what: path >> punct!("!") >> name: option!(ident) >> body: spanned!(delimited) >> cond!(match body.node.delim { DelimToken::Paren | DelimToken::Bracket => true, DelimToken::Brace => false, }, punct!(";")) >> (Item { ident: name.unwrap_or_else(|| Ident::new("")), vis: Visibility::Inherited, attrs: attrs, node: ItemKind::Mac(Mac { path: what, tts: vec![TokenTree::Delimited(body.node, body.span)], }), span: DUMMY_SPAN, }) )); named!(item_extern_crate -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("extern") >> keyword!("crate") >> id: ident >> rename: option!(preceded!( keyword!("as"), ident )) >> punct!(";") >> ({ let (name, original_name) = match rename { Some(rename) => (rename, Some(id)), None => (id, None), }; Item { ident: name, vis: vis, attrs: attrs, node: ItemKind::ExternCrate(original_name), span: DUMMY_SPAN, } }) )); named!(item_use -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("use") >> what: view_path >> punct!(";") >> (Item { ident: "".into(), vis: vis, attrs: attrs, node: ItemKind::Use(Box::new(what)), span: DUMMY_SPAN, }) )); named!(view_path -> ViewPath, alt!( view_path_glob | view_path_list | view_path_list_root | view_path_simple // must be last )); named!(view_path_simple -> ViewPath, do_parse!( path: path >> rename: option!(preceded!(keyword!("as"), ident)) >> (ViewPath::Simple(path, rename)) )); named!(view_path_glob -> ViewPath, do_parse!( path: path >> punct!("::") >> punct!("*") >> (ViewPath::Glob(path)) )); named!(view_path_list -> ViewPath, do_parse!( path: path >> punct!("::") >> punct!("{") >> items: terminated_list!(punct!(","), path_list_item) >> punct!("}") >> (ViewPath::List(path, items)) )); named!(view_path_list_root -> ViewPath, do_parse!( global: option!(punct!("::")) >> punct!("{") >> items: terminated_list!(punct!(","), path_list_item) >> punct!("}") >> (ViewPath::List(Path { global: global.is_some(), segments: Vec::new(), }, items)) )); named!(path_list_item -> PathListItem, do_parse!( name: alt!( ident | map!(keyword!("self"), Into::into) ) >> rename: option!(preceded!(keyword!("as"), ident)) >> (PathListItem { name: name, rename: rename, }) )); named!(item_static -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("static") >> mutability: mutability >> id: ident >> punct!(":") >> ty: ty >> punct!("=") >> value: expr >> punct!(";") >> (Item { ident: id, vis: vis, attrs: attrs, node: ItemKind::Static(Box::new(ty), mutability, Box::new(value)), span: DUMMY_SPAN, }) )); named!(item_const -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("const") >> id: ident >> punct!(":") >> ty: ty >> punct!("=") >> value: expr >> punct!(";") >> (Item { ident: id, vis: vis, attrs: attrs, node: ItemKind::Const(Box::new(ty), Box::new(value)), span: DUMMY_SPAN, }) )); named!(item_fn -> Item, do_parse!( outer_attrs: many0!(outer_attr) >> vis: visibility >> constness: constness >> unsafety: unsafety >> abi: option!(abi) >> keyword!("fn") >> name: ident >> generics: generics >> punct!("(") >> inputs: terminated_list!(punct!(","), fn_arg) >> punct!(")") >> ret: option!(preceded!(punct!("->"), ty)) >> where_clause: where_clause >> punct!("{") >> inner_attrs: many0!(inner_attr) >> stmts: within_block >> punct!("}") >> (Item { ident: name, vis: vis, attrs: { let mut attrs = outer_attrs; attrs.extend(inner_attrs); attrs }, node: ItemKind::Fn( Box::new(FnDecl { inputs: inputs, output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default), variadic: false, }), unsafety, constness, abi, Generics { where_clause: where_clause, .. generics }, Box::new(Block { stmts: stmts, }), ), span: DUMMY_SPAN, }) )); named!(fn_arg -> FnArg, alt!( do_parse!( punct!("&") >> lt: option!(lifetime) >> mutability: mutability >> keyword!("self") >> not!(punct!(":")) >> (FnArg::SelfRef(lt, mutability)) ) | do_parse!( mutability: mutability >> keyword!("self") >> not!(punct!(":")) >> (FnArg::SelfValue(mutability)) ) | do_parse!( pat: pat >> punct!(":") >> ty: ty >> (FnArg::Captured(pat, ty)) ) | ty => { FnArg::Ignored } )); named!(item_mod -> Item, do_parse!( outer_attrs: many0!(outer_attr) >> vis: visibility >> keyword!("mod") >> id: ident >> content: alt!( punct!(";") => { |_| None } | delimited!( punct!("{"), tuple!( many0!(inner_attr), items ), punct!("}") ) => { Some } ) >> (match content { Some((inner_attrs, items)) => Item { ident: id, vis: vis, attrs: { let mut attrs = outer_attrs; attrs.extend(inner_attrs); attrs }, node: ItemKind::Mod(Some(items)), span: DUMMY_SPAN, }, None => Item { ident: id, vis: vis, attrs: outer_attrs, node: ItemKind::Mod(None), span: DUMMY_SPAN, }, }) )); named!(item_foreign_mod -> Item, do_parse!( attrs: many0!(outer_attr) >> abi: abi >> punct!("{") >> items: many0!(foreign_item) >> punct!("}") >> (Item { ident: "".into(), vis: Visibility::Inherited, attrs: attrs, node: ItemKind::ForeignMod(ForeignMod { abi: abi, items: items, }), span: DUMMY_SPAN, }) )); named!(foreign_item -> ForeignItem, add_span!(alt!( foreign_fn | foreign_static ))); named!(foreign_fn -> ForeignItem, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("fn") >> name: ident >> generics: generics >> punct!("(") >> inputs: separated_list!(punct!(","), fn_arg) >> trailing_comma: option!(punct!(",")) >> variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >> punct!(")") >> ret: option!(preceded!(punct!("->"), ty)) >> where_clause: where_clause >> punct!(";") >> (ForeignItem { ident: name, attrs: attrs, node: ForeignItemKind::Fn( Box::new(FnDecl { inputs: inputs, output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default), variadic: variadic.is_some(), }), Generics { where_clause: where_clause, .. generics }, ), vis: vis, span: DUMMY_SPAN, }) )); named!(foreign_static -> ForeignItem, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("static") >> mutability: mutability >> id: ident >> punct!(":") >> ty: ty >> punct!(";") >> (ForeignItem { ident: id, attrs: attrs, node: ForeignItemKind::Static(Box::new(ty), mutability), vis: vis, span: DUMMY_SPAN, }) )); named!(item_ty -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("type") >> id: ident >> generics: generics >> where_clause: where_clause >> punct!("=") >> ty: ty >> punct!(";") >> (Item { ident: id, vis: vis, attrs: attrs, node: ItemKind::Ty( Box::new(ty), Generics { where_clause: where_clause, ..generics }, ), span: DUMMY_SPAN, }) )); named!(item_struct_or_enum -> Item, map!( derive_input, |def: DeriveInput| Item { ident: def.ident, vis: def.vis, attrs: def.attrs, node: match def.body { Body::Enum(variants) => { ItemKind::Enum(variants, def.generics) } Body::Struct(variant_data) => { ItemKind::Struct(variant_data, def.generics) } }, span: DUMMY_SPAN, } )); named!(item_union -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> keyword!("union") >> id: ident >> generics: generics >> where_clause: where_clause >> fields: struct_like_body >> (Item { ident: id, vis: vis, attrs: attrs, node: ItemKind::Union( VariantData::Struct(fields), Generics { where_clause: where_clause, .. generics }, ), span: DUMMY_SPAN, }) )); named!(item_trait -> Item, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> unsafety: unsafety >> keyword!("trait") >> id: ident >> generics: generics >> bounds: opt_vec!(preceded!( punct!(":"), separated_nonempty_list!(punct!("+"), ty_param_bound) )) >> where_clause: where_clause >> punct!("{") >> body: many0!(trait_item) >> punct!("}") >> (Item { ident: id, vis: vis, attrs: attrs, node: ItemKind::Trait( unsafety, Generics { where_clause: where_clause, .. generics }, bounds, body, ), span: DUMMY_SPAN, }) )); named!(item_default_impl -> Item, do_parse!( attrs: many0!(outer_attr) >> unsafety: unsafety >> keyword!("impl") >> path: path >> keyword!("for") >> punct!("..") >> punct!("{") >> punct!("}") >> (Item { ident: "".into(), vis: Visibility::Inherited, attrs: attrs, node: ItemKind::DefaultImpl(unsafety, path), span: DUMMY_SPAN, }) )); named!(trait_item -> TraitItem, add_span!(alt!( trait_item_const | trait_item_method | trait_item_type | trait_item_mac ))); named!(trait_item_const -> TraitItem, do_parse!( attrs: many0!(outer_attr) >> keyword!("const") >> id: ident >> punct!(":") >> ty: ty >> value: option!(preceded!(punct!("="), expr)) >> punct!(";") >> (TraitItem { ident: id, attrs: attrs, node: TraitItemKind::Const(ty, value), span: DUMMY_SPAN, }) )); named!(trait_item_method -> TraitItem, do_parse!( outer_attrs: many0!(outer_attr) >> constness: constness >> unsafety: unsafety >> abi: option!(abi) >> keyword!("fn") >> name: ident >> generics: generics >> punct!("(") >> inputs: terminated_list!(punct!(","), fn_arg) >> punct!(")") >> ret: option!(preceded!(punct!("->"), ty)) >> where_clause: where_clause >> body: option!(delimited!( punct!("{"), tuple!(many0!(inner_attr), within_block), punct!("}") )) >> cond!(body.is_none(), punct!(";")) >> ({ let (inner_attrs, stmts) = match body { Some((inner_attrs, stmts)) => (inner_attrs, Some(stmts)), None => (Vec::new(), None), }; TraitItem { ident: name, attrs: { let mut attrs = outer_attrs; attrs.extend(inner_attrs); attrs }, node: TraitItemKind::Method( MethodSig { unsafety: unsafety, constness: constness, abi: abi, decl: FnDecl { inputs: inputs, output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default), variadic: false, }, generics: Generics { where_clause: where_clause, .. generics }, }, stmts.map(|stmts| Block { stmts: stmts }), ), span: DUMMY_SPAN, } }) )); named!(trait_item_type -> TraitItem, do_parse!( attrs: many0!(outer_attr) >> keyword!("type") >> id: ident >> bounds: opt_vec!(preceded!( punct!(":"), separated_nonempty_list!(punct!("+"), ty_param_bound) )) >> default: option!(preceded!(punct!("="), ty)) >> punct!(";") >> (TraitItem { ident: id, attrs: attrs, node: TraitItemKind::Type(bounds, default), span: DUMMY_SPAN, }) )); named!(trait_item_mac -> TraitItem, do_parse!( attrs: many0!(outer_attr) >> what: path >> punct!("!") >> body: spanned!(delimited) >> cond!(match body.node.delim { DelimToken::Paren | DelimToken::Bracket => true, DelimToken::Brace => false, }, punct!(";")) >> (TraitItem { ident: Ident::new(""), attrs: attrs, node: TraitItemKind::Macro(Mac { path: what, tts: vec![TokenTree::Delimited(body.node, body.span)], }), span: DUMMY_SPAN, }) )); named!(item_impl -> Item, do_parse!( attrs: many0!(outer_attr) >> unsafety: unsafety >> keyword!("impl") >> generics: generics >> polarity_path: alt!( do_parse!( polarity: impl_polarity >> path: path >> keyword!("for") >> ((polarity, Some(path))) ) | epsilon!() => { |_| (ImplPolarity::Positive, None) } ) >> self_ty: ty >> where_clause: where_clause >> punct!("{") >> body: many0!(impl_item) >> punct!("}") >> (Item { ident: "".into(), vis: Visibility::Inherited, attrs: attrs, node: ItemKind::Impl( unsafety, polarity_path.0, Generics { where_clause: where_clause, .. generics }, polarity_path.1, Box::new(self_ty), body, ), span: DUMMY_SPAN, }) )); named!(impl_item -> ImplItem, add_span!(alt!( impl_item_const | impl_item_method | impl_item_type | impl_item_macro ))); named!(impl_item_const -> ImplItem, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> defaultness: defaultness >> keyword!("const") >> id: ident >> punct!(":") >> ty: ty >> punct!("=") >> value: expr >> punct!(";") >> (ImplItem { ident: id, vis: vis, defaultness: defaultness, attrs: attrs, node: ImplItemKind::Const(ty, value), span: DUMMY_SPAN, }) )); named!(impl_item_method -> ImplItem, do_parse!( outer_attrs: many0!(outer_attr) >> vis: visibility >> defaultness: defaultness >> constness: constness >> unsafety: unsafety >> abi: option!(abi) >> keyword!("fn") >> name: ident >> generics: generics >> punct!("(") >> inputs: terminated_list!(punct!(","), fn_arg) >> punct!(")") >> ret: option!(preceded!(punct!("->"), ty)) >> where_clause: where_clause >> punct!("{") >> inner_attrs: many0!(inner_attr) >> stmts: within_block >> punct!("}") >> (ImplItem { ident: name, vis: vis, defaultness: defaultness, attrs: { let mut attrs = outer_attrs; attrs.extend(inner_attrs); attrs }, node: ImplItemKind::Method( MethodSig { unsafety: unsafety, constness: constness, abi: abi, decl: FnDecl { inputs: inputs, output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default), variadic: false, }, generics: Generics { where_clause: where_clause, .. generics }, }, Block { stmts: stmts, }, ), span: DUMMY_SPAN, }) )); named!(impl_item_type -> ImplItem, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> defaultness: defaultness >> keyword!("type") >> id: ident >> punct!("=") >> ty: ty >> punct!(";") >> (ImplItem { ident: id, vis: vis, defaultness: defaultness, attrs: attrs, node: ImplItemKind::Type(ty), span: DUMMY_SPAN, }) )); named!(impl_item_macro -> ImplItem, do_parse!( attrs: many0!(outer_attr) >> what: path >> punct!("!") >> body: spanned!(delimited) >> cond!(match body.node.delim { DelimToken::Paren | DelimToken::Bracket => true, DelimToken::Brace => false, }, punct!(";")) >> (ImplItem { ident: Ident::new(""), vis: Visibility::Inherited, defaultness: Defaultness::Final, attrs: attrs, node: ImplItemKind::Macro(Mac { path: what, tts: vec![TokenTree::Delimited(body.node, body.span)], }), span: DUMMY_SPAN, }) )); named!(impl_polarity -> ImplPolarity, alt!( punct!("!") => { |_| ImplPolarity::Negative } | epsilon!() => { |_| ImplPolarity::Positive } )); named!(constness -> Constness, alt!( keyword!("const") => { |_| Constness::Const } | epsilon!() => { |_| Constness::NotConst } )); named!(defaultness -> Defaultness, alt!( keyword!("default") => { |_| Defaultness::Default } | epsilon!() => { |_| Defaultness::Final } )); } #[cfg(feature = "printing")] mod printing { use super::*; use {Delimited, DelimToken, FunctionRetTy, TokenTree}; use attr::FilterAttrs; use data::VariantData; use quote::{Tokens, ToTokens}; impl ToTokens for Item { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); match self.node { ItemKind::ExternCrate(ref original) => { self.vis.to_tokens(tokens); tokens.append("extern"); tokens.append("crate"); if let Some(ref original) = *original { original.to_tokens(tokens); tokens.append("as"); } self.ident.to_tokens(tokens); tokens.append(";"); } ItemKind::Use(ref view_path) => { self.vis.to_tokens(tokens); tokens.append("use"); view_path.to_tokens(tokens); tokens.append(";"); } ItemKind::Static(ref ty, ref mutability, ref expr) => { self.vis.to_tokens(tokens); tokens.append("static"); mutability.to_tokens(tokens); self.ident.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); tokens.append("="); expr.to_tokens(tokens); tokens.append(";"); } ItemKind::Const(ref ty, ref expr) => { self.vis.to_tokens(tokens); tokens.append("const"); self.ident.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); tokens.append("="); expr.to_tokens(tokens); tokens.append(";"); } ItemKind::Fn(ref decl, unsafety, constness, ref abi, ref generics, ref block) => { self.vis.to_tokens(tokens); constness.to_tokens(tokens); unsafety.to_tokens(tokens); abi.to_tokens(tokens); tokens.append("fn"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); tokens.append("("); tokens.append_separated(&decl.inputs, ","); tokens.append(")"); if let FunctionRetTy::Ty(ref ty) = decl.output { tokens.append("->"); ty.to_tokens(tokens); } generics.where_clause.to_tokens(tokens); tokens.append("{"); tokens.append_all(self.attrs.inner()); tokens.append_all(&block.stmts); tokens.append("}"); } ItemKind::Mod(ref items) => { self.vis.to_tokens(tokens); tokens.append("mod"); self.ident.to_tokens(tokens); match *items { Some(ref items) => { tokens.append("{"); tokens.append_all(self.attrs.inner()); tokens.append_all(items); tokens.append("}"); } None => tokens.append(";"), } } ItemKind::ForeignMod(ref foreign_mod) => { self.vis.to_tokens(tokens); foreign_mod.abi.to_tokens(tokens); tokens.append("{"); tokens.append_all(&foreign_mod.items); tokens.append("}"); } ItemKind::Ty(ref ty, ref generics) => { self.vis.to_tokens(tokens); tokens.append("type"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); generics.where_clause.to_tokens(tokens); tokens.append("="); ty.to_tokens(tokens); tokens.append(";"); } ItemKind::Enum(ref variants, ref generics) => { self.vis.to_tokens(tokens); tokens.append("enum"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); generics.where_clause.to_tokens(tokens); tokens.append("{"); for variant in variants { variant.to_tokens(tokens); tokens.append(","); } tokens.append("}"); } ItemKind::Struct(ref variant_data, ref generics) => { self.vis.to_tokens(tokens); tokens.append("struct"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); match *variant_data { VariantData::Struct(_) => { generics.where_clause.to_tokens(tokens); variant_data.to_tokens(tokens); // no semicolon } VariantData::Tuple(_) => { variant_data.to_tokens(tokens); generics.where_clause.to_tokens(tokens); tokens.append(";"); } VariantData::Unit => { generics.where_clause.to_tokens(tokens); tokens.append(";"); } } } ItemKind::Union(ref variant_data, ref generics) => { self.vis.to_tokens(tokens); tokens.append("union"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); generics.where_clause.to_tokens(tokens); variant_data.to_tokens(tokens); } ItemKind::Trait(unsafety, ref generics, ref bound, ref items) => { self.vis.to_tokens(tokens); unsafety.to_tokens(tokens); tokens.append("trait"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); if !bound.is_empty() { tokens.append(":"); tokens.append_separated(bound, "+"); } generics.where_clause.to_tokens(tokens); tokens.append("{"); tokens.append_all(items); tokens.append("}"); } ItemKind::DefaultImpl(unsafety, ref path) => { unsafety.to_tokens(tokens); tokens.append("impl"); path.to_tokens(tokens); tokens.append("for"); tokens.append(".."); tokens.append("{"); tokens.append("}"); } ItemKind::Impl(unsafety, polarity, ref generics, ref path, ref ty, ref items) => { unsafety.to_tokens(tokens); tokens.append("impl"); generics.to_tokens(tokens); if let Some(ref path) = *path { polarity.to_tokens(tokens); path.to_tokens(tokens); tokens.append("for"); } ty.to_tokens(tokens); generics.where_clause.to_tokens(tokens); tokens.append("{"); tokens.append_all(items); tokens.append("}"); } ItemKind::Mac(ref mac) => { mac.path.to_tokens(tokens); tokens.append("!"); self.ident.to_tokens(tokens); for tt in &mac.tts { tt.to_tokens(tokens); } match mac.tts.last() { Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. }, _)) => { // no semicolon } _ => tokens.append(";"), } } } } } impl ToTokens for ViewPath { fn to_tokens(&self, tokens: &mut Tokens) { match *self { ViewPath::Simple(ref path, ref rename) => { path.to_tokens(tokens); if let Some(ref rename) = *rename { tokens.append("as"); rename.to_tokens(tokens); } } ViewPath::Glob(ref path) => { path.to_tokens(tokens); tokens.append("::"); tokens.append("*"); } ViewPath::List(ref path, ref items) => { path.to_tokens(tokens); if path.global || !path.segments.is_empty() { tokens.append("::"); } tokens.append("{"); tokens.append_separated(items, ","); tokens.append("}"); } } } } impl ToTokens for PathListItem { fn to_tokens(&self, tokens: &mut Tokens) { self.name.to_tokens(tokens); if let Some(ref rename) = self.rename { tokens.append("as"); rename.to_tokens(tokens); } } } impl ToTokens for TraitItem { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); match self.node { TraitItemKind::Const(ref ty, ref expr) => { tokens.append("const"); self.ident.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); if let Some(ref expr) = *expr { tokens.append("="); expr.to_tokens(tokens); } tokens.append(";"); } TraitItemKind::Method(ref sig, ref block) => { sig.constness.to_tokens(tokens); sig.unsafety.to_tokens(tokens); sig.abi.to_tokens(tokens); tokens.append("fn"); self.ident.to_tokens(tokens); sig.generics.to_tokens(tokens); tokens.append("("); tokens.append_separated(&sig.decl.inputs, ","); tokens.append(")"); if let FunctionRetTy::Ty(ref ty) = sig.decl.output { tokens.append("->"); ty.to_tokens(tokens); } sig.generics.where_clause.to_tokens(tokens); match *block { Some(ref block) => { tokens.append("{"); tokens.append_all(self.attrs.inner()); tokens.append_all(&block.stmts); tokens.append("}"); } None => tokens.append(";"), } } TraitItemKind::Type(ref bound, ref default) => { tokens.append("type"); self.ident.to_tokens(tokens); if !bound.is_empty() { tokens.append(":"); tokens.append_separated(bound, "+"); } if let Some(ref default) = *default { tokens.append("="); default.to_tokens(tokens); } tokens.append(";"); } TraitItemKind::Macro(ref mac) => { mac.to_tokens(tokens); match mac.tts.last() { Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. }, _)) => { // no semicolon } _ => tokens.append(";"), } } } } } impl ToTokens for ImplItem { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); match self.node { ImplItemKind::Const(ref ty, ref expr) => { self.vis.to_tokens(tokens); self.defaultness.to_tokens(tokens); tokens.append("const"); self.ident.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); tokens.append("="); expr.to_tokens(tokens); tokens.append(";"); } ImplItemKind::Method(ref sig, ref block) => { self.vis.to_tokens(tokens); self.defaultness.to_tokens(tokens); sig.constness.to_tokens(tokens); sig.unsafety.to_tokens(tokens); sig.abi.to_tokens(tokens); tokens.append("fn"); self.ident.to_tokens(tokens); sig.generics.to_tokens(tokens); tokens.append("("); tokens.append_separated(&sig.decl.inputs, ","); tokens.append(")"); if let FunctionRetTy::Ty(ref ty) = sig.decl.output { tokens.append("->"); ty.to_tokens(tokens); } sig.generics.where_clause.to_tokens(tokens); tokens.append("{"); tokens.append_all(self.attrs.inner()); tokens.append_all(&block.stmts); tokens.append("}"); } ImplItemKind::Type(ref ty) => { self.vis.to_tokens(tokens); self.defaultness.to_tokens(tokens); tokens.append("type"); self.ident.to_tokens(tokens); tokens.append("="); ty.to_tokens(tokens); tokens.append(";"); } ImplItemKind::Macro(ref mac) => { mac.to_tokens(tokens); match mac.tts.last() { Some(&TokenTree::Delimited(Delimited { delim: DelimToken::Brace, .. }, _)) => { // no semicolon } _ => tokens.append(";"), } } } } } impl ToTokens for ForeignItem { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append_all(self.attrs.outer()); match self.node { ForeignItemKind::Fn(ref decl, ref generics) => { self.vis.to_tokens(tokens); tokens.append("fn"); self.ident.to_tokens(tokens); generics.to_tokens(tokens); tokens.append("("); tokens.append_separated(&decl.inputs, ","); if decl.variadic { if !decl.inputs.is_empty() { tokens.append(","); } tokens.append("..."); } tokens.append(")"); if let FunctionRetTy::Ty(ref ty) = decl.output { tokens.append("->"); ty.to_tokens(tokens); } generics.where_clause.to_tokens(tokens); tokens.append(";"); } ForeignItemKind::Static(ref ty, mutability) => { self.vis.to_tokens(tokens); tokens.append("static"); mutability.to_tokens(tokens); self.ident.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); tokens.append(";"); } } } } impl ToTokens for FnArg { fn to_tokens(&self, tokens: &mut Tokens) { match *self { FnArg::SelfRef(ref lifetime, mutability) => { tokens.append("&"); lifetime.to_tokens(tokens); mutability.to_tokens(tokens); tokens.append("self"); } FnArg::SelfValue(mutability) => { mutability.to_tokens(tokens); tokens.append("self"); } FnArg::Captured(ref pat, ref ty) => { pat.to_tokens(tokens); tokens.append(":"); ty.to_tokens(tokens); } FnArg::Ignored(ref ty) => { ty.to_tokens(tokens); } } } } impl ToTokens for Constness { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Constness::Const => tokens.append("const"), Constness::NotConst => { // nothing } } } } impl ToTokens for Defaultness { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Defaultness::Default => tokens.append("default"), Defaultness::Final => { // nothing } } } } impl ToTokens for ImplPolarity { fn to_tokens(&self, tokens: &mut Tokens) { match *self { ImplPolarity::Negative => tokens.append("!"), ImplPolarity::Positive => { // nothing } } } } } cpp_syn-0.12.0/src/krate.rs01006440000765000002400000002530130566610420013732 0ustar0000000000000000use super::*; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Crate { pub shebang: Option, pub attrs: Vec, pub items: Vec, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use attr::parsing::inner_attr; use item::parsing::items; named!(pub krate -> Crate, do_parse!( option!(byte_order_mark) >> shebang: option!(shebang) >> attrs: many0!(inner_attr) >> items: items >> (Crate { shebang: shebang, attrs: attrs, items: items, }) )); named!(byte_order_mark -> &str, tag!("\u{feff}")); named!(shebang -> String, do_parse!( tag!("#!") >> not!(tag!("[")) >> content: take_until!("\n") >> (format!("#!{}", content)) )); } #[cfg(feature = "printing")] mod printing { use super::*; use attr::FilterAttrs; use quote::{Tokens, ToTokens}; impl ToTokens for Crate { fn to_tokens(&self, tokens: &mut Tokens) { if let Some(ref shebang) = self.shebang { tokens.append(&format!("{}\n", shebang)); } for attr in self.attrs.inner() { attr.to_tokens(tokens); } for item in &self.items { item.to_tokens(tokens); } } } } cpp_syn-0.12.0/src/lib.rs01006440000765000002400000014124130566610510013374 0ustar0000000000000000#![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", plugin(clippy))] #[cfg(feature = "printing")] extern crate quote; #[cfg(feature = "parsing")] extern crate unicode_xid; #[cfg(feature = "parsing")] #[macro_use] extern crate cpp_synom as synom; #[cfg(feature = "aster")] pub mod aster; #[macro_use] mod span; pub use span::{Span, Spanned, EMPTY_SPAN, DUMMY_SPAN}; mod attr; pub use attr::{Attribute, AttrStyle, MetaItem, NestedMetaItem}; mod constant; pub use constant::ConstExpr; mod data; pub use data::{Field, Variant, VariantData, Visibility}; #[cfg(feature = "parsing")] mod escape; #[cfg(feature = "full")] mod expr; #[cfg(feature = "full")] pub use expr::{Arm, BindingMode, Block, CaptureBy, Expr, ExprKind, FieldPat, FieldValue, Local, MacStmtStyle, Pat, RangeLimits, Stmt}; mod generics; pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate, WhereRegionPredicate}; #[cfg(feature = "printing")] pub use generics::{ImplGenerics, Turbofish, TyGenerics}; mod ident; pub use ident::Ident; #[cfg(feature = "full")] mod item; #[cfg(feature = "full")] pub use item::{Constness, Defaultness, FnArg, FnDecl, ForeignItemKind, ForeignItem, ForeignMod, ImplItem, ImplItemKind, ImplPolarity, Item, ItemKind, MethodSig, PathListItem, TraitItem, TraitItemKind, ViewPath}; #[cfg(feature = "full")] mod krate; #[cfg(feature = "full")] pub use krate::Crate; mod lit; pub use lit::{FloatTy, IntTy, Lit, LitKind, StrStyle}; #[cfg(feature = "parsing")] pub use lit::{ByteStrLit, FloatLit, IntLit, StrLit}; mod mac; pub use mac::{BinOpToken, DelimToken, Delimited, Mac, Token, TokenTree}; mod derive; pub use derive::{Body, DeriveInput}; // Deprecated. Use `DeriveInput` instead. #[doc(hidden)] pub type MacroInput = DeriveInput; mod op; pub use op::{BinOp, UnOp}; mod ty; pub use ty::{Abi, AngleBracketedParameterData, BareFnArg, BareFnTy, FunctionRetTy, MutTy, Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment, PolyTraitRef, QSelf, Ty, TypeBinding, Unsafety}; #[cfg(feature = "visit")] pub mod visit; #[cfg(feature = "fold")] pub mod fold; #[cfg(feature = "parsing")] pub use parsing::*; #[cfg(feature = "parsing")] mod parsing { use super::*; use {derive, generics, ident, mac, ty}; use synom::{space, IResult, ParseState}; #[cfg(feature = "full")] use {expr, item, krate}; pub fn parse_derive_input(input: &str) -> Result { unwrap("derive input", derive::parsing::derive_input, input) } #[cfg(feature = "full")] pub fn parse_crate(input: &str) -> Result { unwrap("crate", krate::parsing::krate, input) } #[cfg(feature = "full")] pub fn parse_item(input: &str) -> Result { unwrap("item", item::parsing::item, input) } #[cfg(feature = "full")] pub fn parse_items(input: &str) -> Result, String> { unwrap("items", item::parsing::items, input) } #[cfg(feature = "full")] pub fn parse_expr(input: &str) -> Result { unwrap("expression", expr::parsing::expr, input) } pub fn parse_type(input: &str) -> Result { unwrap("type", ty::parsing::ty, input) } pub fn parse_path(input: &str) -> Result { unwrap("path", ty::parsing::path, input) } pub fn parse_where_clause(input: &str) -> Result { unwrap("where clause", generics::parsing::where_clause, input) } pub fn parse_token_trees(input: &str) -> Result, String> { unwrap("token trees", mac::parsing::token_trees, input) } pub fn parse_ident(input: &str) -> Result { unwrap("identifier", ident::parsing::ident, input) } pub fn parse_ty_param_bound(input: &str) -> Result { unwrap("type parameter bound", generics::parsing::ty_param_bound, input) } // Deprecated. Use `parse_derive_input` instead. #[doc(hidden)] pub fn parse_macro_input(input: &str) -> Result { parse_derive_input(input) } fn unwrap(name: &'static str, f: fn(ParseState) -> IResult, input: &str) -> Result { match f(ParseState::new(input)) { IResult::Done(mut rest, t) => { rest = space::skip_whitespace(rest); if rest.is_empty() { Ok(t) } else if rest.len() == input.len() { // parsed nothing Err(format!("failed to parse {}: {:?}", name, rest)) } else { Err(format!("unparsed tokens after {}: {:?}", name, rest)) } } IResult::Error => Err(format!("failed to parse {}: {:?}", name, input)), } } } #[cfg(feature = "parsing")] pub mod parse { //! This module contains a set of exported nom parsers which can be used to //! parse custom grammars when used alongside the `synom` crate. //! //! Internally, `syn` uses a fork of `nom` called `synom` which resolves a //! persistent pitfall of using `nom` to parse Rust by eliminating the //! `IResult::Incomplete` variant. The `synom` crate should be used instead //! of `nom` when working with the parsers in this module. #[cfg(feature = "full")] pub use item::parsing::item; #[cfg(feature = "full")] pub use expr::parsing::expr; pub use lit::parsing::lit; pub use lit::parsing::string; pub use lit::parsing::byte_string; pub use lit::parsing::byte; pub use lit::parsing::character; pub use lit::parsing::float; pub use lit::parsing::int; pub use lit::parsing::boolean; pub use ty::parsing::ty; pub use ty::parsing::path; pub use mac::parsing::token_tree as tt; pub use ident::parsing::ident; pub use generics::parsing::lifetime; } cpp_syn-0.12.0/src/lit.rs01006440000765000002400000035320130566610420013417 0ustar0000000000000000use {Span, Spanned, EMPTY_SPAN}; /// Literal kind. /// /// E.g. `"foo"`, `42`, `12.34` or `bool` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Lit { pub node: LitKind, pub span: Span, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum LitKind { /// A string literal (`"foo"`) Str(String, StrStyle), /// A byte string (`b"foo"`) ByteStr(Vec, StrStyle), /// A byte char (`b'f'`) Byte(u8), /// A character literal (`'a'`) Char(char), /// An integer literal (`1`) Int(u64, IntTy), /// A float literal (`1f64` or `1E10f64` or `1.0E10`) Float(String, FloatTy), /// A boolean literal Bool(bool), } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum StrStyle { /// A regular string, like `"foo"` Cooked, /// A raw string, like `r##"foo"##` /// /// The uint is the number of `#` symbols used Raw(usize), } impl> From> for Lit { fn from(input: Spanned) -> Lit { Lit { span: input.span, ..input.node.into() } } } impl From for Lit { fn from(input: String) -> Lit { Lit { node: LitKind::Str(input, StrStyle::Cooked), span: EMPTY_SPAN, } } } impl<'a> From<&'a str> for Lit { fn from(input: &str) -> Lit { Lit { node: LitKind::Str(input.into(), StrStyle::Cooked), span: EMPTY_SPAN, } } } impl From> for Lit { fn from(input: Vec) -> Lit { Lit { node: LitKind::ByteStr(input, StrStyle::Cooked), span: EMPTY_SPAN, } } } impl<'a> From<&'a [u8]> for Lit { fn from(input: &[u8]) -> Lit { Lit { node: LitKind::ByteStr(input.into(), StrStyle::Cooked), span: EMPTY_SPAN, } } } impl From for Lit { fn from(input: char) -> Lit { Lit { node: LitKind::Char(input), span: EMPTY_SPAN, } } } impl From for Lit { fn from(input: bool) -> Lit { Lit { node: LitKind::Bool(input), span: EMPTY_SPAN, } } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum IntTy { Isize, I8, I16, I32, I64, Usize, U8, U16, U32, U64, Unsuffixed, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum FloatTy { F32, F64, Unsuffixed, } macro_rules! impl_from_for_lit { (Int, [$($rust_type:ty => $syn_type:expr),+]) => { $( impl From<$rust_type> for Lit { fn from(input: $rust_type) -> Lit { Lit { node: LitKind::Int(input as u64, $syn_type), span: EMPTY_SPAN, } } } )+ }; (Float, [$($rust_type:ty => $syn_type:expr),+]) => { $( impl From<$rust_type> for Lit { fn from(input: $rust_type) -> Lit { Lit { node: LitKind::Float(format!("{}", input), $syn_type), span: EMPTY_SPAN, } } } )+ }; } impl_from_for_lit! {Int, [ isize => IntTy::Isize, i8 => IntTy::I8, i16 => IntTy::I16, i32 => IntTy::I32, i64 => IntTy::I64, usize => IntTy::Usize, u8 => IntTy::U8, u16 => IntTy::U16, u32 => IntTy::U32, u64 => IntTy::U64 ]} impl_from_for_lit! {Float, [ f32 => FloatTy::F32, f64 => FloatTy::F64 ]} #[cfg(feature = "parsing")] #[derive(Debug, Clone)] pub struct StrLit { pub value: String, pub style: StrStyle, } #[cfg(feature = "parsing")] #[derive(Debug, Clone)] pub struct ByteStrLit { pub value: Vec, pub style: StrStyle, } #[cfg(feature = "parsing")] #[derive(Debug, Clone)] pub struct IntLit { pub value: u64, pub suffix: IntTy, } #[cfg(feature = "parsing")] #[derive(Debug, Clone)] pub struct FloatLit { pub value: String, pub suffix: FloatTy, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use escape::{cooked_byte, cooked_byte_string, cooked_char, cooked_string, raw_string}; use synom::space::skip_whitespace; use synom::{IResult, ParseState}; use unicode_xid::UnicodeXID; named!(pub lit -> Lit, do_parse!( node: spanned!(alt!( string => { |StrLit { value, style }| LitKind::Str(value, style) } | byte_string => { |ByteStrLit { value, style }| LitKind::ByteStr(value, style) } | byte => { |b| LitKind::Byte(b) } | character => { |ch| LitKind::Char(ch) } | float => { |FloatLit { value, suffix }| LitKind::Float(value, suffix) } // must be before int | int => { |IntLit { value, suffix }| LitKind::Int(value, suffix) } | boolean => { |value| LitKind::Bool(value) } )) >> (Lit { node: node.node, span: node.span, }) )); named!(pub string -> StrLit, alt!( quoted_string => { |s| StrLit { value: s, style: StrStyle::Cooked } } | preceded!( punct!("r"), raw_string ) => { |(s, n)| StrLit { value: s, style: StrStyle::Raw(n) }} )); named!(pub quoted_string -> String, delimited!( punct!("\""), cooked_string, tag!("\"") )); named!(pub byte_string -> ByteStrLit, alt!( delimited!( punct!("b\""), cooked_byte_string, tag!("\"") ) => { |vec| ByteStrLit { value: vec, style: StrStyle::Cooked } } | preceded!( punct!("br"), raw_string ) => { |(s, n): (String, _)| ByteStrLit { value: s.into_bytes(), style: StrStyle::Raw(n) } } )); named!(pub byte -> u8, do_parse!( punct!("b") >> tag!("'") >> b: cooked_byte >> tag!("'") >> (b) )); named!(pub character -> char, do_parse!( punct!("'") >> ch: cooked_char >> tag!("'") >> (ch) )); named!(pub float -> FloatLit, do_parse!( value: float_string >> suffix: alt!( tag!("f32") => { |_| FloatTy::F32 } | tag!("f64") => { |_| FloatTy::F64 } | epsilon!() => { |_| FloatTy::Unsuffixed } ) >> (FloatLit { value: value, suffix: suffix }) )); named!(pub int -> IntLit, do_parse!( value: digits >> suffix: alt!( tag!("isize") => { |_| IntTy::Isize } | tag!("i8") => { |_| IntTy::I8 } | tag!("i16") => { |_| IntTy::I16 } | tag!("i32") => { |_| IntTy::I32 } | tag!("i64") => { |_| IntTy::I64 } | tag!("usize") => { |_| IntTy::Usize } | tag!("u8") => { |_| IntTy::U8 } | tag!("u16") => { |_| IntTy::U16 } | tag!("u32") => { |_| IntTy::U32 } | tag!("u64") => { |_| IntTy::U64 } | epsilon!() => { |_| IntTy::Unsuffixed } ) >> (IntLit { value: value, suffix: suffix }) )); named!(pub boolean -> bool, alt!( keyword!("true") => { |_| true } | keyword!("false") => { |_| false } )); fn float_string(mut input: ParseState) -> IResult { input = skip_whitespace(input); let mut chars = input.chars().peekable(); match chars.next() { Some(ch) if ch >= '0' && ch <= '9' => {} _ => return IResult::Error, } let mut len = 1; let mut has_dot = false; let mut has_exp = false; while let Some(&ch) = chars.peek() { match ch { '0'...'9' | '_' => { chars.next(); len += 1; } '.' => { if has_dot { break; } chars.next(); if chars.peek() .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch)) .unwrap_or(false) { return IResult::Error; } len += 1; has_dot = true; } 'e' | 'E' => { chars.next(); len += 1; has_exp = true; break; } _ => break, } } let rest = input.advance(len); if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { return IResult::Error; } if has_exp { let mut has_exp_value = false; while let Some(&ch) = chars.peek() { match ch { '+' | '-' => { if has_exp_value { break; } chars.next(); len += 1; } '0'...'9' => { chars.next(); len += 1; has_exp_value = true; } '_' => { chars.next(); len += 1; } _ => break, } } if !has_exp_value { return IResult::Error; } } IResult::Done(input.advance(len), input.until(len).replace("_", "")) } pub fn digits(mut input: ParseState) -> IResult { input = skip_whitespace(input); let base = if input.starts_with("0x") { input = input.advance(2); 16 } else if input.starts_with("0o") { input = input.advance(2); 8 } else if input.starts_with("0b") { input = input.advance(2); 2 } else { 10 }; let mut value = 0u64; let mut len = 0; let mut empty = true; for b in input.bytes() { let digit = match b { b'0'...b'9' => (b - b'0') as u64, b'a'...b'f' => 10 + (b - b'a') as u64, b'A'...b'F' => 10 + (b - b'A') as u64, b'_' => { if empty && base == 10 { return IResult::Error; } len += 1; continue; } _ => break, }; if digit >= base { return IResult::Error; } value = match value.checked_mul(base) { Some(value) => value, None => return IResult::Error, }; value = match value.checked_add(digit) { Some(value) => value, None => return IResult::Error, }; len += 1; empty = false; } if empty { IResult::Error } else { IResult::Done(input.advance(len), value) } } } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; use std::{ascii, iter}; use std::fmt::{self, Display}; use std::str; impl ToTokens for Lit { fn to_tokens(&self, tokens: &mut Tokens) { match self.node { LitKind::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens), LitKind::Str(ref s, StrStyle::Raw(n)) => { tokens.append(&format!("r{delim}\"{string}\"{delim}", delim = iter::repeat("#").take(n).collect::(), string = s)); } LitKind::ByteStr(ref v, StrStyle::Cooked) => { let mut escaped = "b\"".to_string(); for &ch in v.iter() { match ch { 0 => escaped.push_str(r"\0"), b'\'' => escaped.push('\''), _ => escaped.extend(ascii::escape_default(ch).map(|c| c as char)), } } escaped.push('"'); tokens.append(&escaped); } LitKind::ByteStr(ref vec, StrStyle::Raw(n)) => { tokens.append(&format!("br{delim}\"{string}\"{delim}", delim = iter::repeat("#").take(n).collect::(), string = str::from_utf8(vec).unwrap())); } LitKind::Byte(b) => { match b { 0 => tokens.append(r"b'\0'"), b'\"' => tokens.append("b'\"'"), _ => { let mut escaped = "b'".to_string(); escaped.extend(ascii::escape_default(b).map(|c| c as char)); escaped.push('\''); tokens.append(&escaped); } } } LitKind::Char(ch) => ch.to_tokens(tokens), LitKind::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)), LitKind::Float(ref value, ty) => tokens.append(&format!("{}{}", value, ty)), LitKind::Bool(true) => tokens.append("true"), LitKind::Bool(false) => tokens.append("false"), } } } impl Display for IntTy { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { IntTy::Isize => formatter.write_str("isize"), IntTy::I8 => formatter.write_str("i8"), IntTy::I16 => formatter.write_str("i16"), IntTy::I32 => formatter.write_str("i32"), IntTy::I64 => formatter.write_str("i64"), IntTy::Usize => formatter.write_str("usize"), IntTy::U8 => formatter.write_str("u8"), IntTy::U16 => formatter.write_str("u16"), IntTy::U32 => formatter.write_str("u32"), IntTy::U64 => formatter.write_str("u64"), IntTy::Unsuffixed => Ok(()), } } } impl Display for FloatTy { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FloatTy::F32 => formatter.write_str("f32"), FloatTy::F64 => formatter.write_str("f64"), FloatTy::Unsuffixed => Ok(()), } } } } cpp_syn-0.12.0/src/mac.rs01006440000765000002400000030475130566610420013375 0ustar0000000000000000use super::*; /// Represents a macro invocation. The Path indicates which macro /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. /// /// NB: the additional ident for a `macro_rules`-style macro is actually /// stored in the enclosing item. Oog. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Mac { pub path: Path, pub tts: Vec, } /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can /// be passed to syntax extensions using a uniform type. /// /// If the syntax extension is an MBE macro, it will attempt to match its /// LHS token tree against the provided token tree, and if it finds a /// match, will transcribe the RHS token tree, splicing in any captured /// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds. /// /// The RHS of an MBE macro is the only place `SubstNt`s are substituted. /// Nothing special happens to misnamed or misplaced `SubstNt`s. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum TokenTree { /// A single token Token(Token, Span), /// A delimited sequence of token trees Delimited(Delimited, Span), } impl TokenTree { pub fn span(&self) -> Span { match *self { TokenTree::Token(_, span) => span, TokenTree::Delimited(_, span) => span, } } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Delimited { /// The type of delimiter pub delim: DelimToken, /// The delimited sequence of token trees pub tts: Vec, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Token { // Expression-operator symbols. Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, BinOp(BinOpToken), BinOpEq(BinOpToken), // Structural symbols At, Dot, DotDot, DotDotDot, Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question, // Literals Literal(Lit), // Name components Ident(Ident), Underscore, Lifetime(Ident), DocComment(String), } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum BinOpToken { Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr, } /// A delimiter token #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum DelimToken { /// A round parenthesis: `(` or `)` Paren, /// A square bracket: `[` or `]` Bracket, /// A curly brace: `{` or `}` Brace, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use Lifetime; use generics::parsing::lifetime; use ident::parsing::word; use lit::parsing::lit; use synom::space::{block_comment, whitespace}; use ty::parsing::path; named!(pub mac -> Mac, do_parse!( what: path >> punct!("!") >> body: spanned!(delimited) >> (Mac { path: what, tts: vec![TokenTree::Delimited(body.node, body.span)], }) )); named!(pub token_trees -> Vec, many0!(token_tree)); named!(pub delimited -> Delimited, alt!( delimited!( punct!("("), token_trees, punct!(")") ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } } | delimited!( punct!("["), token_trees, punct!("]") ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } } | delimited!( punct!("{"), token_trees, punct!("}") ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } } )); named!(pub token_tree -> TokenTree, alt!( spanned!(token) => { |t: Spanned| { TokenTree::Token(t.node, t.span) } } | spanned!(delimited) => { |d: Spanned| { TokenTree::Delimited(d.node, d.span) } } )); named!(token -> Token, alt!( keyword!("_") => { |_| Token::Underscore } | punct!("&&") => { |_| Token::AndAnd } // must be before BinOp | punct!("||") => { |_| Token::OrOr } // must be before BinOp | punct!("->") => { |_| Token::RArrow } // must be before BinOp | punct!("<-") => { |_| Token::LArrow } // must be before Lt | punct!("=>") => { |_| Token::FatArrow } // must be before Eq | punct!("...") => { |_| Token::DotDotDot } // must be before DotDot | punct!("..") => { |_| Token::DotDot } // must be before Dot | punct!(".") => { |_| Token::Dot } | map!(doc_comment, Token::DocComment) // must be before bin_op | map!(bin_op_eq, Token::BinOpEq) // must be before bin_op | map!(bin_op, Token::BinOp) | map!(lit, Token::Literal) | map!(word, Token::Ident) | map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident)) | punct!("<=") => { |_| Token::Le } | punct!("==") => { |_| Token::EqEq } | punct!("!=") => { |_| Token::Ne } | punct!(">=") => { |_| Token::Ge } | punct!("::") => { |_| Token::ModSep } | punct!("=") => { |_| Token::Eq } | punct!("<") => { |_| Token::Lt } | punct!(">") => { |_| Token::Gt } | punct!("!") => { |_| Token::Not } | punct!("~") => { |_| Token::Tilde } | punct!("@") => { |_| Token::At } | punct!(",") => { |_| Token::Comma } | punct!(";") => { |_| Token::Semi } | punct!(":") => { |_| Token::Colon } | punct!("#") => { |_| Token::Pound } | punct!("$") => { |_| Token::Dollar } | punct!("?") => { |_| Token::Question } )); named!(bin_op -> BinOpToken, alt!( punct!("+") => { |_| BinOpToken::Plus } | punct!("-") => { |_| BinOpToken::Minus } | punct!("*") => { |_| BinOpToken::Star } | punct!("/") => { |_| BinOpToken::Slash } | punct!("%") => { |_| BinOpToken::Percent } | punct!("^") => { |_| BinOpToken::Caret } | punct!("&") => { |_| BinOpToken::And } | punct!("|") => { |_| BinOpToken::Or } | punct!("<<") => { |_| BinOpToken::Shl } | punct!(">>") => { |_| BinOpToken::Shr } )); named!(bin_op_eq -> BinOpToken, alt!( punct!("+=") => { |_| BinOpToken::Plus } | punct!("-=") => { |_| BinOpToken::Minus } | punct!("*=") => { |_| BinOpToken::Star } | punct!("/=") => { |_| BinOpToken::Slash } | punct!("%=") => { |_| BinOpToken::Percent } | punct!("^=") => { |_| BinOpToken::Caret } | punct!("&=") => { |_| BinOpToken::And } | punct!("|=") => { |_| BinOpToken::Or } | punct!("<<=") => { |_| BinOpToken::Shl } | punct!(">>=") => { |_| BinOpToken::Shr } )); named!(doc_comment -> String, alt!( do_parse!( punct!("//!") >> content: take_until!("\n") >> (format!("//!{}", content)) ) | do_parse!( option!(whitespace) >> peek!(tag!("/*!")) >> com: block_comment >> (com.to_owned()) ) | do_parse!( punct!("///") >> not!(tag!("/")) >> content: take_until!("\n") >> (format!("///{}", content)) ) | do_parse!( option!(whitespace) >> peek!(tuple!(tag!("/**"), not!(tag!("*")))) >> com: block_comment >> (com.to_owned()) ) )); } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for Mac { fn to_tokens(&self, tokens: &mut Tokens) { self.path.to_tokens(tokens); tokens.append("!"); for tt in &self.tts { tt.to_tokens(tokens); } } } impl ToTokens for TokenTree { fn to_tokens(&self, tokens: &mut Tokens) { match *self { TokenTree::Token(ref token, _) => token.to_tokens(tokens), TokenTree::Delimited(ref delimited, _) => delimited.to_tokens(tokens), } } } impl DelimToken { fn open(&self) -> &'static str { match *self { DelimToken::Paren => "(", DelimToken::Bracket => "[", DelimToken::Brace => "{", } } fn close(&self) -> &'static str { match *self { DelimToken::Paren => ")", DelimToken::Bracket => "]", DelimToken::Brace => "}", } } } impl ToTokens for Delimited { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append(self.delim.open()); for tt in &self.tts { tt.to_tokens(tokens); } tokens.append(self.delim.close()); } } impl ToTokens for Token { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Token::Eq => tokens.append("="), Token::Lt => tokens.append("<"), Token::Le => tokens.append("<="), Token::EqEq => tokens.append("=="), Token::Ne => tokens.append("!="), Token::Ge => tokens.append(">="), Token::Gt => tokens.append(">"), Token::AndAnd => tokens.append("&&"), Token::OrOr => tokens.append("||"), Token::Not => tokens.append("!"), Token::Tilde => tokens.append("~"), Token::BinOp(binop) => tokens.append(binop.op()), Token::BinOpEq(binop) => tokens.append(binop.assign_op()), Token::At => tokens.append("@"), Token::Dot => tokens.append("."), Token::DotDot => tokens.append(".."), Token::DotDotDot => tokens.append("..."), Token::Comma => tokens.append(","), Token::Semi => tokens.append(";"), Token::Colon => tokens.append(":"), Token::ModSep => tokens.append("::"), Token::RArrow => tokens.append("->"), Token::LArrow => tokens.append("<-"), Token::FatArrow => tokens.append("=>"), Token::Pound => tokens.append("#"), Token::Dollar => tokens.append("$"), Token::Question => tokens.append("?"), Token::Literal(ref lit) => lit.to_tokens(tokens), Token::Ident(ref ident) | Token::Lifetime(ref ident) => ident.to_tokens(tokens), Token::Underscore => tokens.append("_"), Token::DocComment(ref com) => { tokens.append(&format!("{}\n", com)); } } } } impl BinOpToken { fn op(&self) -> &'static str { match *self { BinOpToken::Plus => "+", BinOpToken::Minus => "-", BinOpToken::Star => "*", BinOpToken::Slash => "/", BinOpToken::Percent => "%", BinOpToken::Caret => "^", BinOpToken::And => "&", BinOpToken::Or => "|", BinOpToken::Shl => "<<", BinOpToken::Shr => ">>", } } fn assign_op(&self) -> &'static str { match *self { BinOpToken::Plus => "+=", BinOpToken::Minus => "-=", BinOpToken::Star => "*=", BinOpToken::Slash => "/=", BinOpToken::Percent => "%=", BinOpToken::Caret => "^=", BinOpToken::And => "&=", BinOpToken::Or => "|=", BinOpToken::Shl => "<<=", BinOpToken::Shr => ">>=", } } } impl ToTokens for BinOpToken { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append(self.op()); } } } cpp_syn-0.12.0/src/op.rs01006440000765000002400000011513130412351710013235 0ustar0000000000000000#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum BinOp { /// The `+` operator (addition) Add, /// The `-` operator (subtraction) Sub, /// The `*` operator (multiplication) Mul, /// The `/` operator (division) Div, /// The `%` operator (modulus) Rem, /// The `&&` operator (logical and) And, /// The `||` operator (logical or) Or, /// The `^` operator (bitwise xor) BitXor, /// The `&` operator (bitwise and) BitAnd, /// The `|` operator (bitwise or) BitOr, /// The `<<` operator (shift left) Shl, /// The `>>` operator (shift right) Shr, /// The `==` operator (equality) Eq, /// The `<` operator (less than) Lt, /// The `<=` operator (less than or equal to) Le, /// The `!=` operator (not equal to) Ne, /// The `>=` operator (greater than or equal to) Ge, /// The `>` operator (greater than) Gt, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum UnOp { /// The `*` operator for dereferencing Deref, /// The `!` operator for logical inversion Not, /// The `-` operator for negation Neg, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; named!(pub binop -> BinOp, alt!( punct!("&&") => { |_| BinOp::And } | punct!("||") => { |_| BinOp::Or } | punct!("<<") => { |_| BinOp::Shl } | punct!(">>") => { |_| BinOp::Shr } | punct!("==") => { |_| BinOp::Eq } | punct!("<=") => { |_| BinOp::Le } | punct!("!=") => { |_| BinOp::Ne } | punct!(">=") => { |_| BinOp::Ge } | punct!("+") => { |_| BinOp::Add } | punct!("-") => { |_| BinOp::Sub } | punct!("*") => { |_| BinOp::Mul } | punct!("/") => { |_| BinOp::Div } | punct!("%") => { |_| BinOp::Rem } | punct!("^") => { |_| BinOp::BitXor } | punct!("&") => { |_| BinOp::BitAnd } | punct!("|") => { |_| BinOp::BitOr } | punct!("<") => { |_| BinOp::Lt } | punct!(">") => { |_| BinOp::Gt } )); #[cfg(feature = "full")] named!(pub assign_op -> BinOp, alt!( punct!("+=") => { |_| BinOp::Add } | punct!("-=") => { |_| BinOp::Sub } | punct!("*=") => { |_| BinOp::Mul } | punct!("/=") => { |_| BinOp::Div } | punct!("%=") => { |_| BinOp::Rem } | punct!("^=") => { |_| BinOp::BitXor } | punct!("&=") => { |_| BinOp::BitAnd } | punct!("|=") => { |_| BinOp::BitOr } | punct!("<<=") => { |_| BinOp::Shl } | punct!(">>=") => { |_| BinOp::Shr } )); named!(pub unop -> UnOp, alt!( punct!("*") => { |_| UnOp::Deref } | punct!("!") => { |_| UnOp::Not } | punct!("-") => { |_| UnOp::Neg } )); } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl BinOp { pub fn op(&self) -> &'static str { match *self { BinOp::Add => "+", BinOp::Sub => "-", BinOp::Mul => "*", BinOp::Div => "/", BinOp::Rem => "%", BinOp::And => "&&", BinOp::Or => "||", BinOp::BitXor => "^", BinOp::BitAnd => "&", BinOp::BitOr => "|", BinOp::Shl => "<<", BinOp::Shr => ">>", BinOp::Eq => "==", BinOp::Lt => "<", BinOp::Le => "<=", BinOp::Ne => "!=", BinOp::Ge => ">=", BinOp::Gt => ">", } } pub fn assign_op(&self) -> Option<&'static str> { match *self { BinOp::Add => Some("+="), BinOp::Sub => Some("-="), BinOp::Mul => Some("*="), BinOp::Div => Some("/="), BinOp::Rem => Some("%="), BinOp::BitXor => Some("^="), BinOp::BitAnd => Some("&="), BinOp::BitOr => Some("|="), BinOp::Shl => Some("<<="), BinOp::Shr => Some(">>="), _ => None, } } } impl ToTokens for BinOp { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append(self.op()); } } impl UnOp { pub fn op(&self) -> &'static str { match *self { UnOp::Deref => "*", UnOp::Not => "!", UnOp::Neg => "-", } } } impl ToTokens for UnOp { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append(self.op()); } } } cpp_syn-0.12.0/src/span.rs01006440000765000002400000003617130566610420013574 0ustar0000000000000000use std::usize; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct Span { pub lo: usize, pub hi: usize, } impl Span { pub fn extend(self, other: Span) -> Span { Span { lo: self.lo, hi: other.hi, } } } pub const EMPTY_SPAN: Span = Span { lo: 0, hi: 0 }; pub const DUMMY_SPAN: Span = Span { lo: usize::MAX, hi: usize::MAX }; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct Spanned { pub node: T, pub span: Span, } #[cfg(feature = "parsing")] #[macro_use] mod parsing { #[macro_export] macro_rules! spanned { ($i:expr, $submac:ident!( $($args:tt)* )) => { match $submac!($i, $($args)*) { ::synom::IResult::Done(rest, node) => { let span = $crate::Span { lo: ::synom::space::skip_whitespace($i).idx(), hi: rest.idx() }; ::synom::IResult::Done(rest, $crate::Spanned { node: node, span: span }) } ::synom::IResult::Error => ::synom::IResult::Error, } }; ($i:expr, $f:expr) => { spanned!($i, call!($f)) }; } #[macro_export] macro_rules! add_span { ($i:expr, $submac:ident!( $($args:tt)* )) => { match $submac!($i, $($args)*) { ::synom::IResult::Done(rest, mut val) => { assert_eq!(val.span, $crate::DUMMY_SPAN); val.span = $crate::Span { lo: ::synom::space::skip_whitespace($i).idx(), hi: rest.idx() }; ::synom::IResult::Done(rest, val) } ::synom::IResult::Error => ::synom::IResult::Error, } }; ($i:expr, $f:expr) => { spanned!($i, call!($f)) }; } } cpp_syn-0.12.0/src/ty.rs01006440000765000002400000061062130566610420013265 0ustar0000000000000000use super::*; /// The different kinds of types recognized by the compiler #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Ty { /// A variable-length array (`[T]`) Slice(Box), /// A fixed length array (`[T; n]`) Array(Box, ConstExpr), /// A raw pointer (`*const T` or `*mut T`) Ptr(Box), /// A reference (`&'a T` or `&'a mut T`) Rptr(Option, Box), /// A bare function (e.g. `fn(usize) -> bool`) BareFn(Box), /// The never type (`!`) Never, /// A tuple (`(A, B, C, D, ...)`) Tup(Vec), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g. ` as SomeTrait>::SomeType`. /// /// Type parameters are stored in the Path itself Path(Option, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(Vec), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. ImplTrait(Vec), /// No-op; kept solely so that we can pretty-print faithfully Paren(Box), /// TyKind::Infer means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, /// A macro in the type position. Mac(Mac), } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct MutTy { pub ty: Ty, pub mutability: Mutability, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Mutability { Mutable, Immutable, } /// A "Path" is essentially Rust's notion of a name. /// /// It's represented as a sequence of identifiers, /// along with a bunch of supporting information. /// /// E.g. `std::cmp::PartialEq` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Path { /// A `::foo` path, is relative to the crate root rather than current /// module (like paths in an import). pub global: bool, /// The segments in the path: the things separated by `::`. pub segments: Vec, } impl From for Path where T: Into { fn from(segment: T) -> Self { Path { global: false, segments: vec![segment.into()], } } } /// A segment of a path: an identifier, an optional lifetime, and a set of types. /// /// E.g. `std`, `String` or `Box` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. Note that /// this is more than just simple syntactic sugar; the use of /// parens affects the region binding rules, so we preserve the /// distinction. pub parameters: PathParameters, } impl From for PathSegment where T: Into { fn from(ident: T) -> Self { PathSegment { ident: ident.into(), parameters: PathParameters::none(), } } } /// Parameters of a path segment. /// /// E.g. `` as in `Foo` or `(A, B)` as in `Foo(A, B)` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum PathParameters { /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>` AngleBracketed(AngleBracketedParameterData), /// The `(A, B)` and `C` in `Foo(A, B) -> C` Parenthesized(ParenthesizedParameterData), } impl PathParameters { pub fn none() -> Self { PathParameters::AngleBracketed(AngleBracketedParameterData::default()) } pub fn is_empty(&self) -> bool { match *self { PathParameters::AngleBracketed(ref bracketed) => { bracketed.lifetimes.is_empty() && bracketed.types.is_empty() && bracketed.bindings.is_empty() } PathParameters::Parenthesized(_) => false, } } } /// A path like `Foo<'a, T>` #[derive(Debug, Clone, Eq, PartialEq, Default, Hash)] pub struct AngleBracketedParameterData { /// The lifetime parameters for this path segment. pub lifetimes: Vec, /// The type parameters for this path segment, if present. pub types: Vec, /// Bindings (equality constraints) on associated types, if present. /// /// E.g., `Foo`. pub bindings: Vec, } /// Bind a type to an associated type: `A=Foo`. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct TypeBinding { pub ident: Ident, pub ty: Ty, } /// A path like `Foo(A,B) -> C` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct ParenthesizedParameterData { /// `(A, B)` pub inputs: Vec, /// `C` pub output: Option, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct PolyTraitRef { /// The `'a` in `<'a> Foo<&'a T>` pub bound_lifetimes: Vec, /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` pub trait_ref: Path, } /// The explicit Self type in a "qualified path". The actual /// path, including the trait and the associated item, is stored /// separately. `position` represents the index of the associated /// item qualified with this Self type. /// /// ```rust,ignore /// as a::b::Trait>::AssociatedItem /// ^~~~~ ~~~~~~~~~~~~~~^ /// ty position = 3 /// /// >::AssociatedItem /// ^~~~~ ^ /// ty position = 0 /// ``` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct QSelf { pub ty: Box, pub position: usize, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct BareFnTy { pub unsafety: Unsafety, pub abi: Option, pub lifetimes: Vec, pub inputs: Vec, pub output: FunctionRetTy, pub variadic: bool, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Unsafety { Unsafe, Normal, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Abi { Named(String), Rust, } /// An argument in a function type. /// /// E.g. `bar: usize` as in `fn foo(bar: usize)` #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct BareFnArg { pub name: Option, pub ty: Ty, } #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum FunctionRetTy { /// Return type is not specified. /// /// Functions default to `()` and /// closures default to inference. Span points to where return /// type would be inserted. Default, /// Everything else Ty(Ty), } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use {TyParamBound, TraitBoundModifier}; #[cfg(feature = "full")] use ConstExpr; use constant::parsing::const_expr; #[cfg(feature = "full")] use expr::parsing::expr; use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes}; use ident::parsing::ident; use lit::parsing::quoted_string; use mac::parsing::mac; named!(pub ty -> Ty, alt!( ty_paren // must be before ty_tup | ty_mac // must be before ty_path | ty_path // must be before ty_poly_trait_ref | ty_vec | ty_array | ty_ptr | ty_rptr | ty_bare_fn | ty_never | ty_tup | ty_poly_trait_ref | ty_impl_trait )); named!(ty_mac -> Ty, map!(mac, Ty::Mac)); named!(ty_vec -> Ty, do_parse!( punct!("[") >> elem: ty >> punct!("]") >> (Ty::Slice(Box::new(elem))) )); #[cfg(not(feature = "full"))] named!(ty_array -> Ty, do_parse!( punct!("[") >> elem: ty >> punct!(";") >> len: const_expr >> punct!("]") >> (Ty::Array(Box::new(elem), len)) )); #[cfg(feature = "full")] named!(ty_array -> Ty, do_parse!( punct!("[") >> elem: ty >> punct!(";") >> len: alt!( terminated!(const_expr, punct!("]")) | terminated!(expr, punct!("]")) => { ConstExpr::Other } ) >> (Ty::Array(Box::new(elem), len)) )); named!(ty_ptr -> Ty, do_parse!( punct!("*") >> mutability: alt!( keyword!("const") => { |_| Mutability::Immutable } | keyword!("mut") => { |_| Mutability::Mutable } ) >> target: ty >> (Ty::Ptr(Box::new(MutTy { ty: target, mutability: mutability, }))) )); named!(ty_rptr -> Ty, do_parse!( punct!("&") >> life: option!(lifetime) >> mutability: mutability >> target: ty >> (Ty::Rptr(life, Box::new(MutTy { ty: target, mutability: mutability, }))) )); named!(ty_bare_fn -> Ty, do_parse!( lifetimes: opt_vec!(do_parse!( keyword!("for") >> punct!("<") >> lifetimes: terminated_list!(punct!(","), lifetime_def) >> punct!(">") >> (lifetimes) )) >> unsafety: unsafety >> abi: option!(abi) >> keyword!("fn") >> punct!("(") >> inputs: separated_list!(punct!(","), fn_arg) >> trailing_comma: option!(punct!(",")) >> variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >> punct!(")") >> output: option!(preceded!( punct!("->"), ty )) >> (Ty::BareFn(Box::new(BareFnTy { unsafety: unsafety, abi: abi, lifetimes: lifetimes, inputs: inputs, output: match output { Some(ty) => FunctionRetTy::Ty(ty), None => FunctionRetTy::Default, }, variadic: variadic.is_some(), }))) )); named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never)); named!(ty_tup -> Ty, do_parse!( punct!("(") >> elems: terminated_list!(punct!(","), ty) >> punct!(")") >> (Ty::Tup(elems)) )); named!(ty_path -> Ty, do_parse!( qpath: qpath >> parenthesized: cond!( qpath.1.segments.last().unwrap().parameters == PathParameters::none(), option!(parenthesized_parameter_data) ) >> bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >> ({ let (qself, mut path) = qpath; if let Some(Some(parenthesized)) = parenthesized { path.segments.last_mut().unwrap().parameters = parenthesized; } if bounds.is_empty() { Ty::Path(qself, path) } else { let path = TyParamBound::Trait( PolyTraitRef { bound_lifetimes: Vec::new(), trait_ref: path, }, TraitBoundModifier::None, ); let bounds = Some(path).into_iter().chain(bounds).collect(); Ty::TraitObject(bounds) } }) )); named!(parenthesized_parameter_data -> PathParameters, do_parse!( punct!("(") >> inputs: terminated_list!(punct!(","), ty) >> punct!(")") >> output: option!(preceded!( punct!("->"), ty )) >> (PathParameters::Parenthesized( ParenthesizedParameterData { inputs: inputs, output: output, }, )) )); named!(pub qpath -> (Option, Path), alt!( map!(path, |p| (None, p)) | do_parse!( punct!("<") >> this: map!(ty, Box::new) >> path: option!(preceded!( keyword!("as"), path )) >> punct!(">") >> punct!("::") >> rest: separated_nonempty_list!(punct!("::"), path_segment) >> ({ match path { Some(mut path) => { let pos = path.segments.len(); path.segments.extend(rest); (Some(QSelf { ty: this, position: pos }), path) } None => { (Some(QSelf { ty: this, position: 0 }), Path { global: false, segments: rest, }) } } }) ) | map!(keyword!("self"), |_| (None, "self".into())) )); named!(ty_poly_trait_ref -> Ty, map!( separated_nonempty_list!(punct!("+"), ty_param_bound), Ty::TraitObject )); named!(ty_impl_trait -> Ty, do_parse!( keyword!("impl") >> elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >> (Ty::ImplTrait(elem)) )); named!(ty_paren -> Ty, do_parse!( punct!("(") >> elem: ty >> punct!(")") >> (Ty::Paren(Box::new(elem))) )); named!(pub mutability -> Mutability, alt!( keyword!("mut") => { |_| Mutability::Mutable } | epsilon!() => { |_| Mutability::Immutable } )); named!(pub path -> Path, do_parse!( global: option!(punct!("::")) >> segments: separated_nonempty_list!(punct!("::"), path_segment) >> (Path { global: global.is_some(), segments: segments, }) )); named!(path_segment -> PathSegment, alt!( do_parse!( id: option!(ident) >> punct!("<") >> lifetimes: separated_list!(punct!(","), lifetime) >> types: opt_vec!(preceded!( cond!(!lifetimes.is_empty(), punct!(",")), separated_nonempty_list!( punct!(","), terminated!(ty, not!(punct!("="))) ) )) >> bindings: opt_vec!(preceded!( cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")), separated_nonempty_list!(punct!(","), type_binding) )) >> cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >> punct!(">") >> (PathSegment { ident: id.unwrap_or_else(|| "".into()), parameters: PathParameters::AngleBracketed( AngleBracketedParameterData { lifetimes: lifetimes, types: types, bindings: bindings, } ), }) ) | map!(ident, Into::into) | map!(alt!( keyword!("super") | keyword!("self") | keyword!("Self") ), Into::into) )); named!(type_binding -> TypeBinding, do_parse!( id: ident >> punct!("=") >> ty: ty >> (TypeBinding { ident: id, ty: ty, }) )); named!(pub poly_trait_ref -> PolyTraitRef, do_parse!( bound_lifetimes: bound_lifetimes >> trait_ref: path >> parenthesized: option!(cond_reduce!( trait_ref.segments.last().unwrap().parameters == PathParameters::none(), parenthesized_parameter_data )) >> ({ let mut trait_ref = trait_ref; if let Some(parenthesized) = parenthesized { trait_ref.segments.last_mut().unwrap().parameters = parenthesized; } PolyTraitRef { bound_lifetimes: bound_lifetimes, trait_ref: trait_ref, } }) )); named!(pub fn_arg -> BareFnArg, do_parse!( name: option!(do_parse!( name: ident >> punct!(":") >> not!(tag!(":")) >> // not :: (name) )) >> ty: ty >> (BareFnArg { name: name, ty: ty, }) )); named!(pub unsafety -> Unsafety, alt!( keyword!("unsafe") => { |_| Unsafety::Unsafe } | epsilon!() => { |_| Unsafety::Normal } )); named!(pub abi -> Abi, do_parse!( keyword!("extern") >> name: option!(quoted_string) >> (match name { Some(name) => Abi::Named(name), None => Abi::Rust, }) )); } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for Ty { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Ty::Slice(ref inner) => { tokens.append("["); inner.to_tokens(tokens); tokens.append("]"); } Ty::Array(ref inner, ref len) => { tokens.append("["); inner.to_tokens(tokens); tokens.append(";"); len.to_tokens(tokens); tokens.append("]"); } Ty::Ptr(ref target) => { tokens.append("*"); match target.mutability { Mutability::Mutable => tokens.append("mut"), Mutability::Immutable => tokens.append("const"), } target.ty.to_tokens(tokens); } Ty::Rptr(ref lifetime, ref target) => { tokens.append("&"); lifetime.to_tokens(tokens); target.mutability.to_tokens(tokens); target.ty.to_tokens(tokens); } Ty::BareFn(ref func) => { func.to_tokens(tokens); } Ty::Never => { tokens.append("!"); } Ty::Tup(ref elems) => { tokens.append("("); tokens.append_separated(elems, ","); if elems.len() == 1 { tokens.append(","); } tokens.append(")"); } Ty::Path(None, ref path) => { path.to_tokens(tokens); } Ty::Path(Some(ref qself), ref path) => { tokens.append("<"); qself.ty.to_tokens(tokens); if qself.position > 0 { tokens.append("as"); for (i, segment) in path.segments .iter() .take(qself.position) .enumerate() { if i > 0 || path.global { tokens.append("::"); } segment.to_tokens(tokens); } } tokens.append(">"); for segment in path.segments.iter().skip(qself.position) { tokens.append("::"); segment.to_tokens(tokens); } } Ty::TraitObject(ref bounds) => { tokens.append_separated(bounds, "+"); } Ty::ImplTrait(ref bounds) => { tokens.append("impl"); tokens.append_separated(bounds, "+"); } Ty::Paren(ref inner) => { tokens.append("("); inner.to_tokens(tokens); tokens.append(")"); } Ty::Infer => { tokens.append("_"); } Ty::Mac(ref mac) => mac.to_tokens(tokens), } } } impl ToTokens for Mutability { fn to_tokens(&self, tokens: &mut Tokens) { if let Mutability::Mutable = *self { tokens.append("mut"); } } } impl ToTokens for Path { fn to_tokens(&self, tokens: &mut Tokens) { for (i, segment) in self.segments.iter().enumerate() { if i > 0 || self.global { tokens.append("::"); } segment.to_tokens(tokens); } } } impl ToTokens for PathSegment { fn to_tokens(&self, tokens: &mut Tokens) { self.ident.to_tokens(tokens); if self.ident.as_ref().is_empty() && self.parameters.is_empty() { tokens.append("<"); tokens.append(">"); } else { self.parameters.to_tokens(tokens); } } } impl ToTokens for PathParameters { fn to_tokens(&self, tokens: &mut Tokens) { match *self { PathParameters::AngleBracketed(ref parameters) => { parameters.to_tokens(tokens); } PathParameters::Parenthesized(ref parameters) => { parameters.to_tokens(tokens); } } } } impl ToTokens for AngleBracketedParameterData { fn to_tokens(&self, tokens: &mut Tokens) { let has_lifetimes = !self.lifetimes.is_empty(); let has_types = !self.types.is_empty(); let has_bindings = !self.bindings.is_empty(); if !has_lifetimes && !has_types && !has_bindings { return; } tokens.append("<"); let mut first = true; for lifetime in &self.lifetimes { if !first { tokens.append(","); } lifetime.to_tokens(tokens); first = false; } for ty in &self.types { if !first { tokens.append(","); } ty.to_tokens(tokens); first = false; } for binding in &self.bindings { if !first { tokens.append(","); } binding.to_tokens(tokens); first = false; } tokens.append(">"); } } impl ToTokens for TypeBinding { fn to_tokens(&self, tokens: &mut Tokens) { self.ident.to_tokens(tokens); tokens.append("="); self.ty.to_tokens(tokens); } } impl ToTokens for ParenthesizedParameterData { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append("("); tokens.append_separated(&self.inputs, ","); tokens.append(")"); if let Some(ref output) = self.output { tokens.append("->"); output.to_tokens(tokens); } } } impl ToTokens for PolyTraitRef { fn to_tokens(&self, tokens: &mut Tokens) { if !self.bound_lifetimes.is_empty() { tokens.append("for"); tokens.append("<"); tokens.append_separated(&self.bound_lifetimes, ","); tokens.append(">"); } self.trait_ref.to_tokens(tokens); } } impl ToTokens for BareFnTy { fn to_tokens(&self, tokens: &mut Tokens) { if !self.lifetimes.is_empty() { tokens.append("for"); tokens.append("<"); tokens.append_separated(&self.lifetimes, ","); tokens.append(">"); } self.unsafety.to_tokens(tokens); self.abi.to_tokens(tokens); tokens.append("fn"); tokens.append("("); tokens.append_separated(&self.inputs, ","); if self.variadic { if !self.inputs.is_empty() { tokens.append(","); } tokens.append("..."); } tokens.append(")"); if let FunctionRetTy::Ty(ref ty) = self.output { tokens.append("->"); ty.to_tokens(tokens); } } } impl ToTokens for BareFnArg { fn to_tokens(&self, tokens: &mut Tokens) { if let Some(ref name) = self.name { name.to_tokens(tokens); tokens.append(":"); } self.ty.to_tokens(tokens); } } impl ToTokens for Unsafety { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Unsafety::Unsafe => tokens.append("unsafe"), Unsafety::Normal => { // nothing } } } } impl ToTokens for Abi { fn to_tokens(&self, tokens: &mut Tokens) { tokens.append("extern"); match *self { Abi::Named(ref named) => named.to_tokens(tokens), Abi::Rust => {} } } } } cpp_syn-0.12.0/src/visit.rs01006440000765000002400000067336130417612700013777 0ustar0000000000000000// Adapted from libsyntax. //! AST walker. Each overridden visit method has full control over what //! happens with its node, it can do its own traversal of the node's children, //! call `visit::walk_*` to apply the default traversal algorithm, or prevent //! deeper traversal by doing nothing. //! //! Note: it is an important invariant that the default visitor walks the body //! of a function in "execution order" (more concretely, reverse post-order //! with respect to the CFG implied by the AST), meaning that if AST node A may //! execute before AST node B, then A is visited first. The borrow checker in //! particular relies on this property. //! //! Note: walking an AST before macro expansion is probably a bad idea. For //! instance, a walker looking for item names in a module will miss all of //! those that are created by the expansion of a macro. use super::*; /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; /// e.g. the `visit_mod` method by default calls `visit::walk_mod`. /// /// If you want to ensure that your code handles every variant /// explicitly, you need to override each method. (And you also need /// to monitor future changes to `Visitor` in case a new method with a /// new default implementation gets introduced.) pub trait Visitor: Sized { fn visit_ident(&mut self, _ident: &Ident) {} fn visit_derive_input(&mut self, derive_input: &DeriveInput) { walk_derive_input(self, derive_input) } fn visit_ty(&mut self, ty: &Ty) { walk_ty(self, ty) } fn visit_generics(&mut self, generics: &Generics) { walk_generics(self, generics) } fn visit_ty_param_bound(&mut self, bound: &TyParamBound) { walk_ty_param_bound(self, bound) } fn visit_poly_trait_ref(&mut self, trait_ref: &PolyTraitRef, modifier: &TraitBoundModifier) { walk_poly_trait_ref(self, trait_ref, modifier) } fn visit_variant_data(&mut self, data: &VariantData, _ident: &Ident, _generics: &Generics) { walk_variant_data(self, data) } fn visit_field(&mut self, field: &Field) { walk_field(self, field) } fn visit_variant(&mut self, variant: &Variant, generics: &Generics) { walk_variant(self, variant, generics) } fn visit_lifetime(&mut self, _lifetime: &Lifetime) {} fn visit_lifetime_def(&mut self, lifetime: &LifetimeDef) { walk_lifetime_def(self, lifetime) } fn visit_path(&mut self, path: &Path) { walk_path(self, path) } fn visit_path_segment(&mut self, path_segment: &PathSegment) { walk_path_segment(self, path_segment) } fn visit_path_parameters(&mut self, path_parameters: &PathParameters) { walk_path_parameters(self, path_parameters) } fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) { walk_assoc_type_binding(self, type_binding) } fn visit_attribute(&mut self, _attr: &Attribute) {} fn visit_fn_ret_ty(&mut self, ret_ty: &FunctionRetTy) { walk_fn_ret_ty(self, ret_ty) } fn visit_const_expr(&mut self, expr: &ConstExpr) { walk_const_expr(self, expr) } fn visit_lit(&mut self, _lit: &Lit) {} fn visit_mac(&mut self, mac: &Mac) { walk_mac(self, mac); } #[cfg(feature = "full")] fn visit_crate(&mut self, _crate: &Crate) { walk_crate(self, _crate); } #[cfg(feature = "full")] fn visit_item(&mut self, item: &Item) { walk_item(self, item); } #[cfg(feature = "full")] fn visit_expr(&mut self, expr: &Expr) { walk_expr(self, expr); } #[cfg(feature = "full")] fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { walk_foreign_item(self, foreign_item); } #[cfg(feature = "full")] fn visit_pat(&mut self, pat: &Pat) { walk_pat(self, pat); } #[cfg(feature = "full")] fn visit_fn_decl(&mut self, fn_decl: &FnDecl) { walk_fn_decl(self, fn_decl); } #[cfg(feature = "full")] fn visit_trait_item(&mut self, trait_item: &TraitItem) { walk_trait_item(self, trait_item); } #[cfg(feature = "full")] fn visit_impl_item(&mut self, impl_item: &ImplItem) { walk_impl_item(self, impl_item); } #[cfg(feature = "full")] fn visit_method_sig(&mut self, method_sig: &MethodSig) { walk_method_sig(self, method_sig); } #[cfg(feature = "full")] fn visit_stmt(&mut self, stmt: &Stmt) { walk_stmt(self, stmt); } #[cfg(feature = "full")] fn visit_local(&mut self, local: &Local) { walk_local(self, local); } #[cfg(feature = "full")] fn visit_view_path(&mut self, view_path: &ViewPath) { walk_view_path(self, view_path); } } macro_rules! walk_list { ($visitor:expr, $method:ident, $list:expr $(, $extra_args:expr)*) => { for elem in $list { $visitor.$method(elem $(, $extra_args)*) } }; } pub fn walk_opt_ident(visitor: &mut V, opt_ident: &Option) { if let Some(ref ident) = *opt_ident { visitor.visit_ident(ident); } } pub fn walk_lifetime_def(visitor: &mut V, lifetime_def: &LifetimeDef) { visitor.visit_lifetime(&lifetime_def.lifetime); walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); } pub fn walk_poly_trait_ref(visitor: &mut V, trait_ref: &PolyTraitRef, _: &TraitBoundModifier) where V: Visitor { walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); visitor.visit_path(&trait_ref.trait_ref); } pub fn walk_derive_input(visitor: &mut V, derive_input: &DeriveInput) { visitor.visit_ident(&derive_input.ident); visitor.visit_generics(&derive_input.generics); match derive_input.body { Body::Enum(ref variants) => { walk_list!(visitor, visit_variant, variants, &derive_input.generics); } Body::Struct(ref variant_data) => { visitor.visit_variant_data(variant_data, &derive_input.ident, &derive_input.generics); } } walk_list!(visitor, visit_attribute, &derive_input.attrs); } pub fn walk_variant(visitor: &mut V, variant: &Variant, generics: &Generics) where V: Visitor { visitor.visit_ident(&variant.ident); visitor.visit_variant_data(&variant.data, &variant.ident, generics); walk_list!(visitor, visit_attribute, &variant.attrs); } pub fn walk_ty(visitor: &mut V, ty: &Ty) { match *ty { Ty::Slice(ref inner) | Ty::Paren(ref inner) => visitor.visit_ty(inner), Ty::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty), Ty::Rptr(ref opt_lifetime, ref mutable_type) => { walk_list!(visitor, visit_lifetime, opt_lifetime); visitor.visit_ty(&mutable_type.ty) } Ty::Never | Ty::Infer => {} Ty::Tup(ref tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } Ty::BareFn(ref bare_fn) => { walk_list!(visitor, visit_lifetime_def, &bare_fn.lifetimes); for argument in &bare_fn.inputs { walk_opt_ident(visitor, &argument.name); visitor.visit_ty(&argument.ty) } visitor.visit_fn_ret_ty(&bare_fn.output) } Ty::Path(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path); } Ty::Array(ref inner, ref len) => { visitor.visit_ty(inner); visitor.visit_const_expr(len); } Ty::TraitObject(ref bounds) | Ty::ImplTrait(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } Ty::Mac(ref mac) => { visitor.visit_mac(mac); } } } pub fn walk_path(visitor: &mut V, path: &Path) { for segment in &path.segments { visitor.visit_path_segment(segment); } } pub fn walk_path_segment(visitor: &mut V, segment: &PathSegment) { visitor.visit_ident(&segment.ident); visitor.visit_path_parameters(&segment.parameters); } pub fn walk_path_parameters(visitor: &mut V, path_parameters: &PathParameters) where V: Visitor { match *path_parameters { PathParameters::AngleBracketed(ref data) => { walk_list!(visitor, visit_ty, &data.types); walk_list!(visitor, visit_lifetime, &data.lifetimes); walk_list!(visitor, visit_assoc_type_binding, &data.bindings); } PathParameters::Parenthesized(ref data) => { walk_list!(visitor, visit_ty, &data.inputs); walk_list!(visitor, visit_ty, &data.output); } } } pub fn walk_assoc_type_binding(visitor: &mut V, type_binding: &TypeBinding) { visitor.visit_ident(&type_binding.ident); visitor.visit_ty(&type_binding.ty); } pub fn walk_ty_param_bound(visitor: &mut V, bound: &TyParamBound) { match *bound { TyParamBound::Trait(ref ty, ref modifier) => { visitor.visit_poly_trait_ref(ty, modifier); } TyParamBound::Region(ref lifetime) => { visitor.visit_lifetime(lifetime); } } } pub fn walk_generics(visitor: &mut V, generics: &Generics) { for param in &generics.ty_params { visitor.visit_ident(¶m.ident); walk_list!(visitor, visit_ty_param_bound, ¶m.bounds); walk_list!(visitor, visit_ty, ¶m.default); } walk_list!(visitor, visit_lifetime_def, &generics.lifetimes); for predicate in &generics.where_clause.predicates { match *predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { ref bounded_ty, ref bounds, ref bound_lifetimes, .. }) => { visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_lifetime_def, bound_lifetimes); } WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, ref bounds, .. }) => { visitor.visit_lifetime(lifetime); walk_list!(visitor, visit_lifetime, bounds); } WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { visitor.visit_ty(lhs_ty); visitor.visit_ty(rhs_ty); } } } } pub fn walk_fn_ret_ty(visitor: &mut V, ret_ty: &FunctionRetTy) { if let FunctionRetTy::Ty(ref output_ty) = *ret_ty { visitor.visit_ty(output_ty) } } pub fn walk_variant_data(visitor: &mut V, data: &VariantData) { walk_list!(visitor, visit_field, data.fields()); } pub fn walk_field(visitor: &mut V, field: &Field) { walk_opt_ident(visitor, &field.ident); visitor.visit_ty(&field.ty); walk_list!(visitor, visit_attribute, &field.attrs); } pub fn walk_const_expr(visitor: &mut V, len: &ConstExpr) { match *len { ConstExpr::Call(ref function, ref args) => { visitor.visit_const_expr(function); walk_list!(visitor, visit_const_expr, args); } ConstExpr::Binary(_op, ref left, ref right) => { visitor.visit_const_expr(left); visitor.visit_const_expr(right); } ConstExpr::Unary(_op, ref v) => { visitor.visit_const_expr(v); } ConstExpr::Lit(ref lit) => { visitor.visit_lit(lit); } ConstExpr::Cast(ref expr, ref ty) => { visitor.visit_const_expr(expr); visitor.visit_ty(ty); } ConstExpr::Path(ref path) => { visitor.visit_path(path); } ConstExpr::Index(ref expr, ref index) => { visitor.visit_const_expr(expr); visitor.visit_const_expr(index); } ConstExpr::Paren(ref expr) => { visitor.visit_const_expr(expr); } ConstExpr::Other(ref other) => { #[cfg(feature = "full")] fn walk_other(visitor: &mut V, other: &Expr) { visitor.visit_expr(other); } #[cfg(not(feature = "full"))] fn walk_other(_: &mut V, _: &super::constant::Other) {} walk_other(visitor, other); } } } pub fn walk_mac(visitor: &mut V, mac: &Mac) { visitor.visit_path(&mac.path); } #[cfg(feature = "full")] pub fn walk_crate(visitor: &mut V, _crate: &Crate) { walk_list!(visitor, visit_attribute, &_crate.attrs); walk_list!(visitor, visit_item, &_crate.items); } #[cfg(feature = "full")] pub fn walk_item(visitor: &mut V, item: &Item) { visitor.visit_ident(&item.ident); walk_list!(visitor, visit_attribute, &item.attrs); match item.node { ItemKind::ExternCrate(ref ident) => { walk_opt_ident(visitor, ident); } ItemKind::Use(ref view_path) => { visitor.visit_view_path(view_path); } ItemKind::Static(ref ty, _, ref expr) => { visitor.visit_ty(ty); visitor.visit_expr(expr); } ItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); visitor.visit_expr(expr); } ItemKind::Fn(ref decl, _, _, _, ref generics, ref body) => { visitor.visit_fn_decl(decl); visitor.visit_generics(generics); walk_list!(visitor, visit_stmt, &body.stmts); } ItemKind::Mod(ref maybe_items) => { if let Some(ref items) = *maybe_items { walk_list!(visitor, visit_item, items); } } ItemKind::ForeignMod(ref foreign_mod) => { walk_list!(visitor, visit_foreign_item, &foreign_mod.items); } ItemKind::Ty(ref ty, ref generics) => { visitor.visit_ty(ty); visitor.visit_generics(generics); } ItemKind::Enum(ref variant, ref generics) => { walk_list!(visitor, visit_variant, variant, generics); } ItemKind::Struct(ref variant_data, ref generics) => { visitor.visit_variant_data(variant_data, &item.ident, generics); } ItemKind::Union(ref variant_data, ref generics) => { visitor.visit_variant_data(variant_data, &item.ident, generics); } ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => { visitor.visit_generics(generics); walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_trait_item, trait_items); } ItemKind::DefaultImpl(_, ref path) => { visitor.visit_path(path); } ItemKind::Impl(_, _, ref generics, ref maybe_path, ref ty, ref impl_items) => { visitor.visit_generics(generics); if let Some(ref path) = *maybe_path { visitor.visit_path(path); } visitor.visit_ty(ty); walk_list!(visitor, visit_impl_item, impl_items); } ItemKind::Mac(ref mac) => { visitor.visit_mac(mac) } } } #[cfg(feature = "full")] pub fn walk_expr(visitor: &mut V, expr: &Expr) { walk_list!(visitor, visit_attribute, &expr.attrs); match expr.node { ExprKind::Box(ref expr) => { visitor.visit_expr(expr); } ExprKind::InPlace(ref place, ref value) => { visitor.visit_expr(place); visitor.visit_expr(value); } ExprKind::Array(ref exprs) => { walk_list!(visitor, visit_expr, exprs); } ExprKind::Call(ref callee, ref args) => { visitor.visit_expr(callee); walk_list!(visitor, visit_expr, args); } ExprKind::MethodCall(ref name, ref ty_args, ref args) => { visitor.visit_ident(name); walk_list!(visitor, visit_ty, ty_args); walk_list!(visitor, visit_expr, args); } ExprKind::Tup(ref exprs) => { walk_list!(visitor, visit_expr, exprs); } ExprKind::Binary(_, ref lhs, ref rhs) => { visitor.visit_expr(lhs); visitor.visit_expr(rhs); } ExprKind::Unary(_, ref operand) => { visitor.visit_expr(operand); } ExprKind::Lit(ref lit) => { visitor.visit_lit(lit); } ExprKind::Cast(ref expr, ref ty) => { visitor.visit_expr(expr); visitor.visit_ty(ty); } ExprKind::Type(ref expr, ref ty) => { visitor.visit_expr(expr); visitor.visit_ty(ty); } ExprKind::If(ref cond, ref cons, ref maybe_alt) => { visitor.visit_expr(cond); walk_list!(visitor, visit_stmt, &cons.stmts); if let Some(ref alt) = *maybe_alt { visitor.visit_expr(alt); } } ExprKind::IfLet(ref pat, ref cond, ref cons, ref maybe_alt) => { visitor.visit_pat(pat); visitor.visit_expr(cond); walk_list!(visitor, visit_stmt, &cons.stmts); if let Some(ref alt) = *maybe_alt { visitor.visit_expr(alt); } } ExprKind::While(ref cond, ref body, ref label) => { visitor.visit_expr(cond); walk_list!(visitor, visit_stmt, &body.stmts); walk_opt_ident(visitor, label); } ExprKind::WhileLet(ref pat, ref cond, ref body, ref label) => { visitor.visit_pat(pat); visitor.visit_expr(cond); walk_list!(visitor, visit_stmt, &body.stmts); walk_opt_ident(visitor, label); } ExprKind::ForLoop(ref pat, ref expr, ref body, ref label) => { visitor.visit_pat(pat); visitor.visit_expr(expr); walk_list!(visitor, visit_stmt, &body.stmts); walk_opt_ident(visitor, label); } ExprKind::Loop(ref body, ref label) => { walk_list!(visitor, visit_stmt, &body.stmts); walk_opt_ident(visitor, label); } ExprKind::Match(ref expr, ref arms) => { visitor.visit_expr(expr); for &Arm{ref attrs, ref pats, ref guard, ref body} in arms { walk_list!(visitor, visit_attribute, attrs); walk_list!(visitor, visit_pat, pats); if let Some(ref guard) = *guard { visitor.visit_expr(guard); } visitor.visit_expr(body); } } ExprKind::Closure(_, ref decl, ref expr) => { visitor.visit_fn_decl(decl); visitor.visit_expr(expr); } ExprKind::Block(_, ref block) => { walk_list!(visitor, visit_stmt, &block.stmts); } ExprKind::Assign(ref lhs, ref rhs) => { visitor.visit_expr(lhs); visitor.visit_expr(rhs); } ExprKind::AssignOp(_, ref lhs, ref rhs) => { visitor.visit_expr(lhs); visitor.visit_expr(rhs); } ExprKind::Field(ref obj, ref field) => { visitor.visit_expr(obj); visitor.visit_ident(field); } ExprKind::TupField(ref obj, _) => { visitor.visit_expr(obj); } ExprKind::Index(ref obj, ref idx) => { visitor.visit_expr(obj); visitor.visit_expr(idx); } ExprKind::Range(ref maybe_start, ref maybe_end, _) => { if let Some(ref start) = *maybe_start { visitor.visit_expr(start); } if let Some(ref end) = *maybe_end { visitor.visit_expr(end); } } ExprKind::Path(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path); } ExprKind::AddrOf(_, ref expr) => { visitor.visit_expr(expr); } ExprKind::Break(ref maybe_label, ref maybe_expr) => { walk_opt_ident(visitor, maybe_label); if let Some(ref expr) = *maybe_expr { visitor.visit_expr(expr); } } ExprKind::Continue(ref maybe_label) => { walk_opt_ident(visitor, maybe_label); } ExprKind::Ret(ref maybe_expr) => { if let Some(ref expr) = *maybe_expr { visitor.visit_expr(expr); } } ExprKind::Mac(ref mac) => { visitor.visit_mac(mac); } ExprKind::Struct(ref path, ref fields, ref maybe_base) => { visitor.visit_path(path); for &FieldValue{ref ident, ref expr, ..} in fields { visitor.visit_ident(ident); visitor.visit_expr(expr); } if let Some(ref base) = *maybe_base { visitor.visit_expr(base); } } ExprKind::Repeat(ref value, ref times) => { visitor.visit_expr(value); visitor.visit_expr(times); } ExprKind::Paren(ref expr) => { visitor.visit_expr(expr); } ExprKind::Try(ref expr) => { visitor.visit_expr(expr); } } } #[cfg(feature = "full")] pub fn walk_foreign_item(visitor: &mut V, foreign_item: &ForeignItem) { visitor.visit_ident(&foreign_item.ident); walk_list!(visitor, visit_attribute, &foreign_item.attrs); match foreign_item.node { ForeignItemKind::Fn(ref decl, ref generics) => { visitor.visit_fn_decl(decl); visitor.visit_generics(generics); } ForeignItemKind::Static(ref ty, _) => { visitor.visit_ty(ty); } } } #[cfg(feature = "full")] pub fn walk_pat(visitor: &mut V, pat: &Pat) { match *pat { Pat::Wild => {} Pat::Ident(_, ref ident, ref maybe_pat) => { visitor.visit_ident(ident); if let Some(ref pat) = *maybe_pat { visitor.visit_pat(pat); } } Pat::Struct(ref path, ref field_pats, _) => { visitor.visit_path(path); for &FieldPat{ref ident, ref pat, ..} in field_pats { visitor.visit_ident(ident); visitor.visit_pat(pat); } } Pat::TupleStruct(ref path, ref pats, _) => { visitor.visit_path(path); walk_list!(visitor, visit_pat, pats); } Pat::Path(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path); } Pat::Tuple(ref pats, _) => { walk_list!(visitor, visit_pat, pats); } Pat::Box(ref pat) | Pat::Ref(ref pat, _) => { visitor.visit_pat(pat); } Pat::Lit(ref expr) => { visitor.visit_expr(expr); } Pat::Range(ref start, ref end) => { visitor.visit_expr(start); visitor.visit_expr(end); } Pat::Slice(ref start, ref maybe_mid, ref end) => { walk_list!(visitor, visit_pat, start); if let Some(ref mid) = *maybe_mid { visitor.visit_pat(mid); } walk_list!(visitor, visit_pat, end); } Pat::Mac(ref mac) => { visitor.visit_mac(mac); } } } #[cfg(feature = "full")] pub fn walk_fn_decl(visitor: &mut V, fn_decl: &FnDecl) { for input in &fn_decl.inputs { match *input { FnArg::SelfRef(_, _) | FnArg::SelfValue(_) => {} FnArg::Captured(ref pat, ref ty) => { visitor.visit_pat(pat); visitor.visit_ty(ty); } FnArg::Ignored(ref ty) => { visitor.visit_ty(ty); } } } visitor.visit_fn_ret_ty(&fn_decl.output); } #[cfg(feature = "full")] pub fn walk_trait_item(visitor: &mut V, trait_item: &TraitItem) { visitor.visit_ident(&trait_item.ident); walk_list!(visitor, visit_attribute, &trait_item.attrs); match trait_item.node { TraitItemKind::Const(ref ty, ref maybe_expr) => { visitor.visit_ty(ty); if let Some(ref expr) = *maybe_expr { visitor.visit_expr(expr); } } TraitItemKind::Method(ref method_sig, ref maybe_block) => { visitor.visit_method_sig(method_sig); if let Some(ref block) = *maybe_block { walk_list!(visitor, visit_stmt, &block.stmts); } } TraitItemKind::Type(ref bounds, ref maybe_ty) => { walk_list!(visitor, visit_ty_param_bound, bounds); if let Some(ref ty) = *maybe_ty { visitor.visit_ty(ty); } } TraitItemKind::Macro(ref mac) => { visitor.visit_mac(mac); } } } #[cfg(feature = "full")] pub fn walk_impl_item(visitor: &mut V, impl_item: &ImplItem) { visitor.visit_ident(&impl_item.ident); walk_list!(visitor, visit_attribute, &impl_item.attrs); match impl_item.node { ImplItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); visitor.visit_expr(expr); } ImplItemKind::Method(ref method_sig, ref block) => { visitor.visit_method_sig(method_sig); walk_list!(visitor, visit_stmt, &block.stmts); } ImplItemKind::Type(ref ty) => { visitor.visit_ty(ty); } ImplItemKind::Macro(ref mac) => { visitor.visit_mac(mac); } } } #[cfg(feature = "full")] pub fn walk_method_sig(visitor: &mut V, method_sig: &MethodSig) { visitor.visit_fn_decl(&method_sig.decl); visitor.visit_generics(&method_sig.generics); } #[cfg(feature = "full")] pub fn walk_stmt(visitor: &mut V, stmt: &Stmt) { match *stmt { Stmt::Local(ref local) => { visitor.visit_local(local); } Stmt::Item(ref item) => { visitor.visit_item(item); } Stmt::Expr(ref expr) | Stmt::Semi(ref expr) => { visitor.visit_expr(expr); } Stmt::Mac(ref details) => { let (ref mac, _, ref attrs) = **details; visitor.visit_mac(mac); walk_list!(visitor, visit_attribute, attrs); } } } #[cfg(feature = "full")] pub fn walk_local(visitor: &mut V, local: &Local) { visitor.visit_pat(&local.pat); if let Some(ref ty) = local.ty { visitor.visit_ty(ty); } if let Some(ref init) = local.init { visitor.visit_expr(init); } walk_list!(visitor, visit_attribute, &local.attrs); } #[cfg(feature = "full")] pub fn walk_view_path(visitor: &mut V, view_path: &ViewPath) { match *view_path { ViewPath::Simple(ref path, ref maybe_ident) => { visitor.visit_path(path); walk_opt_ident(visitor, maybe_ident); } ViewPath::Glob(ref path) => { visitor.visit_path(path); } ViewPath::List(ref path, ref items) => { visitor.visit_path(path); for &PathListItem{ref name, ref rename} in items { visitor.visit_ident(name); walk_opt_ident(visitor, rename); } } } }