use syntax::ast::*;
use syntax::codemap::{Span};
use syntax::ext::base::{ExtCtxt};
use syntax::parse::{PResult};
use syntax::parse::parser::{Parser};
use syntax::ptr::{P};
use syntax::tokenstream::{TokenTree};
#[doc(hidden)]
pub fn parse_tts<'a, T, F: Fn(&mut Parser<'a>) -> PResult<'a, T>>(
context: &ExtCtxt<'a>, span: Span, tts: &[TokenTree], f: F
) -> Option<T> {
let mut parser = context.new_parser_from_tts(tts);
match f(&mut parser) {
Ok(ok) => Some(ok),
Err(mut err) => {
if err.span.primary_span().map_or(true, |s| s == ::syntax::codemap::DUMMY_SP) {
err.set_span(span);
}
err.emit();
None
},
}
}
#[doc(hidden)]
pub fn parse_bare_fn_ty(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> P<BareFnTy> {
match parse_tts(context, span, tts, |p| p.parse_ty()).unwrap().node {
TyKind::BareFn(ref ty) => ty.clone(),
_ => {
context.span_err(span, "expected bare fn ty");
panic!();
},
}
}
#[doc(hidden)]
pub fn parse_expr(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> Option<P<Expr>> {
parse_tts(context, span, tts, |p| p.parse_expr())
}
#[doc(hidden)]
pub fn parse_field_pat(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> FieldPat {
match parse_tts(context, span, tts, |p| p.parse_pat()).unwrap().node {
PatKind::Struct(_, ref pats, _) => if !pats.is_empty() {
pats[0].node.clone()
} else {
context.span_err(span, "expected field pat");
panic!();
},
_ => unreachable!(),
}
}
#[doc(hidden)]
pub fn parse_foreign_item(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> ForeignItem {
match parse_tts(context, span, tts, |p| p.parse_item()).unwrap().unwrap().node {
ItemKind::ForeignMod(ref foreign) => if !foreign.items.is_empty() {
foreign.items[0].clone()
} else {
context.span_err(span, "expected foreign item");
panic!();
},
_ => unreachable!(),
}
}
#[doc(hidden)]
pub fn parse_foreign_mod(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> ForeignMod {
match parse_tts(context, span, tts, |p| p.parse_item()).unwrap().map(|i| i.node.clone()) {
Some(ItemKind::ForeignMod(foreign)) => foreign,
_ => {
context.span_err(span, "expected foreign mod");
panic!();
},
}
}
#[doc(hidden)]
pub fn parse_lifetime(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> Lifetime {
let mut parser = context.new_parser_from_tts(tts);
if let Some(lifetime) = parser.eat_lifetime() {
lifetime
} else {
context.span_err(span, "expected lifetime");
panic!();
}
}
#[doc(hidden)]
pub fn parse_local(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> P<Local> {
match parse_tts(context, span, tts, |p| p.parse_stmt()).unwrap().map(|s| s.node.clone()) {
Some(StmtKind::Local(local)) => local,
_ => {
context.span_err(span, "expected local");
panic!();
},
}
}
#[doc(hidden)]
pub fn parse_struct_field(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> StructField {
match parse_tts(context, span, tts, |p| p.parse_item()).unwrap().map(|i| i.node.clone()) {
Some(ItemKind::Struct(VariantData::Struct(ref fields, _), _)) => if !fields.is_empty() {
fields[0].clone()
} else {
context.span_err(span, "expected struct field");
panic!();
},
_ => unreachable!(),
}
}
#[doc(hidden)]
pub fn parse_variant(context: &ExtCtxt, span: Span, tts: &[TokenTree]) -> Variant {
match parse_tts(context, span, tts, |p| p.parse_item()).unwrap().map(|i| i.node.clone()) {
Some(ItemKind::Enum(ref def, _)) => if !def.variants.is_empty() {
def.variants[0].clone()
} else {
context.span_err(span, "expected variant");
panic!();
},
_ => unreachable!(),
}
}