1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#[cfg(feature = "parsing")]
#[macro_use]
extern crate nom;

#[cfg(feature = "printing")]
extern crate quote;

#[macro_use]
mod do_parse;

#[macro_use]
mod helper;

mod escape;

mod attr;
pub use attr::{
    Attribute,
    MetaItem,
};

mod generics;
pub use generics::{
    Generics,
    Lifetime,
    LifetimeDef,
    TraitBoundModifier,
    TyParam,
    TyParamBound,
    WhereBoundPredicate,
    WhereClause,
    WherePredicate,
    WhereRegionPredicate,
};

mod ident;
pub use ident::{
    Ident,
};

mod item;
pub use item::{
    Body,
    Field,
    Item,
    Variant,
    VariantData,
    Visibility,
};

mod ty;
pub use ty::{
    AngleBracketedParameterData,
    BareFnTy,
    FnArg,
    FnDecl,
    FunctionRetTy,
    MutTy,
    Mutability,
    ParenthesizedParameterData,
    Path,
    PathParameters,
    PathSegment,
    PolyTraitRef,
    QSelf,
    Ty,
    TypeBinding,
};

#[cfg(feature = "aster")]
pub mod aster;

#[cfg(feature = "visit")]
pub mod visit;

#[cfg(feature = "parsing")]
pub use parsing::*;

#[cfg(feature = "parsing")]
mod parsing {
    use super::*;
    use {generics, item, ty};
    use nom;

    pub fn parse_item(input: &str) -> Result<Item, String> {
        unwrap("item", item::parsing::item(input))
    }

    pub fn parse_type(input: &str) -> Result<Ty, String> {
        unwrap("type", ty::parsing::ty(input))
    }

    pub fn parse_path(input: &str) -> Result<Path, String> {
        unwrap("path", ty::parsing::path(input))
    }

    pub fn parse_where_clause(input: &str) -> Result<WhereClause, String> {
        unwrap("where clause", generics::parsing::where_clause(input))
    }

    fn unwrap<T>(name: &'static str, ires: nom::IResult<&str, T>) -> Result<T, String> {
        return match ires {
            nom::IResult::Done(rest, t) => {
                if rest.is_empty() {
                    Ok(t)
                } else {
                    Err(format!("remaining tokens after {}: {:?}", name, rest))
                }
            }
            nom::IResult::Error(err) => Err(root_cause(err)),
            nom::IResult::Incomplete(_) => Err(format!("incomplete {}", name)),
        };

        fn root_cause(mut err: nom::Err<&str>) -> String {
            loop {
                match err {
                    nom::Err::Code(kind) => {
                        return format!("failed to parse {:?}", kind);
                    }
                    nom::Err::Position(kind, pos) => {
                        return format!("failed to parse {:?}: {:?}", kind, pos);
                    }
                    nom::Err::Node(_, next) |
                    nom::Err::NodePosition(_, _, next) => {
                        err = *next;
                    }
                }
            }
        }
    }
}