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
#[cfg(feature = "parsing")]
#[macro_use]
extern crate nom;

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

#[macro_use]
mod do_parse;

#[macro_use]
mod helper;

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;
                    }
                }
            }
        }
    }
}