Refactor parse_expansion
out of ResultAnyMacro
.
This commit is contained in:
parent
5fc14c1a6f
commit
8b40eaddf1
2 changed files with 63 additions and 92 deletions
|
@ -21,9 +21,9 @@ use ext::base::*;
|
|||
use feature_gate::{self, Features};
|
||||
use fold;
|
||||
use fold::*;
|
||||
use parse::{ParseSess, lexer};
|
||||
use parse::{ParseSess, PResult, lexer};
|
||||
use parse::parser::Parser;
|
||||
use parse::token::{intern, keywords};
|
||||
use parse::token::{self, intern, keywords};
|
||||
use print::pprust;
|
||||
use ptr::P;
|
||||
use tokenstream::{TokenTree, TokenStream};
|
||||
|
@ -38,12 +38,12 @@ macro_rules! expansions {
|
|||
($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
|
||||
$(.$fold:ident)* $(lift .$fold_elt:ident)*,
|
||||
$(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ExpansionKind { OptExpr, $( $kind, )* }
|
||||
pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
|
||||
|
||||
impl ExpansionKind {
|
||||
fn name(self) -> &'static str {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
ExpansionKind::OptExpr => "expression",
|
||||
$( ExpansionKind::$kind => $kind_name, )*
|
||||
|
@ -106,6 +106,12 @@ macro_rules! expansions {
|
|||
self.expand(Expansion::$kind(SmallVector::one(node))).$make()
|
||||
})*)*
|
||||
}
|
||||
|
||||
impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
|
||||
$(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
|
||||
Some(self.make(ExpansionKind::$kind).$make())
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,6 +456,47 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn parse_expansion(&mut self, kind: ExpansionKind) -> PResult<'a, Expansion> {
|
||||
Ok(match kind {
|
||||
ExpansionKind::Items => {
|
||||
let mut items = SmallVector::zero();
|
||||
while let Some(item) = self.parse_item()? {
|
||||
items.push(item);
|
||||
}
|
||||
Expansion::Items(items)
|
||||
}
|
||||
ExpansionKind::TraitItems => {
|
||||
let mut items = SmallVector::zero();
|
||||
while self.token != token::Eof {
|
||||
items.push(self.parse_trait_item()?);
|
||||
}
|
||||
Expansion::TraitItems(items)
|
||||
}
|
||||
ExpansionKind::ImplItems => {
|
||||
let mut items = SmallVector::zero();
|
||||
while self.token != token::Eof {
|
||||
items.push(self.parse_impl_item()?);
|
||||
}
|
||||
Expansion::ImplItems(items)
|
||||
}
|
||||
ExpansionKind::Stmts => {
|
||||
let mut stmts = SmallVector::zero();
|
||||
while self.token != token::Eof {
|
||||
if let Some(stmt) = self.parse_full_stmt(true)? {
|
||||
stmts.push(stmt);
|
||||
}
|
||||
}
|
||||
Expansion::Stmts(stmts)
|
||||
}
|
||||
ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
|
||||
ExpansionKind::OptExpr => Expansion::OptExpr(Some(self.parse_expr()?)),
|
||||
ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
|
||||
ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct InvocationCollector<'a, 'b: 'a> {
|
||||
cx: &'a mut ExtCtxt<'b>,
|
||||
cfg: StripUnconfigured<'a>,
|
||||
|
|
|
@ -12,6 +12,7 @@ use {ast, attr};
|
|||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension};
|
||||
use ext::base::{IdentMacroExpander, NormalTT, TTMacroExpander};
|
||||
use ext::expand::{Expansion, ExpansionKind};
|
||||
use ext::placeholders;
|
||||
use ext::tt::macro_parser::{Success, Error, Failure};
|
||||
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||
|
@ -22,18 +23,14 @@ use parse::parser::{Parser, Restrictions};
|
|||
use parse::token::{self, gensym_ident, NtTT, Token};
|
||||
use parse::token::Token::*;
|
||||
use print;
|
||||
use ptr::P;
|
||||
use tokenstream::{self, TokenTree};
|
||||
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap};
|
||||
use std::collections::hash_map::{Entry};
|
||||
use std::rc::Rc;
|
||||
|
||||
struct ParserAnyMacro<'a> {
|
||||
parser: RefCell<Parser<'a>>,
|
||||
pub struct ParserAnyMacro<'a> {
|
||||
parser: Parser<'a>,
|
||||
|
||||
/// Span of the expansion site of the macro this parser is for
|
||||
site_span: Span,
|
||||
|
@ -48,8 +45,8 @@ impl<'a> ParserAnyMacro<'a> {
|
|||
/// about e.g. the semicolon in `macro_rules! kapow { () => {
|
||||
/// panic!(); } }` doesn't get picked up by .parse_expr(), but it's
|
||||
/// allowed to be there.
|
||||
fn ensure_complete_parse(&self, allow_semi: bool, context: &str) {
|
||||
let mut parser = self.parser.borrow_mut();
|
||||
fn ensure_complete_parse(&mut self, allow_semi: bool, context: &str) {
|
||||
let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self;
|
||||
parser.ensure_complete_parse(allow_semi, |parser| {
|
||||
let token_str = parser.this_token_to_string();
|
||||
let msg = format!("macro expansion ignores token `{}` and any \
|
||||
|
@ -59,89 +56,16 @@ impl<'a> ParserAnyMacro<'a> {
|
|||
let mut err = parser.diagnostic().struct_span_err(span, &msg);
|
||||
let msg = format!("caused by the macro expansion here; the usage \
|
||||
of `{}!` is likely invalid in {} context",
|
||||
self.macro_ident, context);
|
||||
err.span_note(self.site_span, &msg)
|
||||
macro_ident, context);
|
||||
err.span_note(site_span, &msg)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MacResult for ParserAnyMacro<'a> {
|
||||
fn make_expr(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Expr>> {
|
||||
let ret = panictry!(self.parser.borrow_mut().parse_expr());
|
||||
self.ensure_complete_parse(true, "expression");
|
||||
Some(ret)
|
||||
}
|
||||
fn make_pat(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Pat>> {
|
||||
let ret = panictry!(self.parser.borrow_mut().parse_pat());
|
||||
self.ensure_complete_parse(false, "pattern");
|
||||
Some(ret)
|
||||
}
|
||||
fn make_items(self: Box<ParserAnyMacro<'a>>) -> Option<SmallVector<P<ast::Item>>> {
|
||||
let mut ret = SmallVector::zero();
|
||||
while let Some(item) = panictry!(self.parser.borrow_mut().parse_item()) {
|
||||
ret.push(item);
|
||||
}
|
||||
self.ensure_complete_parse(false, "item");
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
fn make_impl_items(self: Box<ParserAnyMacro<'a>>)
|
||||
-> Option<SmallVector<ast::ImplItem>> {
|
||||
let mut ret = SmallVector::zero();
|
||||
loop {
|
||||
let mut parser = self.parser.borrow_mut();
|
||||
match parser.token {
|
||||
token::Eof => break,
|
||||
_ => ret.push(panictry!(parser.parse_impl_item()))
|
||||
}
|
||||
}
|
||||
self.ensure_complete_parse(false, "item");
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
fn make_trait_items(self: Box<ParserAnyMacro<'a>>)
|
||||
-> Option<SmallVector<ast::TraitItem>> {
|
||||
let mut ret = SmallVector::zero();
|
||||
loop {
|
||||
let mut parser = self.parser.borrow_mut();
|
||||
match parser.token {
|
||||
token::Eof => break,
|
||||
_ => ret.push(panictry!(parser.parse_trait_item()))
|
||||
}
|
||||
}
|
||||
self.ensure_complete_parse(false, "item");
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
|
||||
fn make_stmts(self: Box<ParserAnyMacro<'a>>)
|
||||
-> Option<SmallVector<ast::Stmt>> {
|
||||
let mut ret = SmallVector::zero();
|
||||
loop {
|
||||
let mut parser = self.parser.borrow_mut();
|
||||
match parser.token {
|
||||
token::Eof => break,
|
||||
_ => match parser.parse_full_stmt(true) {
|
||||
Ok(maybe_stmt) => match maybe_stmt {
|
||||
Some(stmt) => ret.push(stmt),
|
||||
None => (),
|
||||
},
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ensure_complete_parse(false, "statement");
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
fn make_ty(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Ty>> {
|
||||
let ret = panictry!(self.parser.borrow_mut().parse_ty());
|
||||
self.ensure_complete_parse(false, "type");
|
||||
Some(ret)
|
||||
pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: ExpansionKind) -> Expansion {
|
||||
let expansion = panictry!(self.parser.parse_expansion(kind));
|
||||
self.ensure_complete_parse(kind == ExpansionKind::Expr, kind.name());
|
||||
expansion
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +143,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
|
|||
// Let the context choose how to interpret the result.
|
||||
// Weird, but useful for X-macros.
|
||||
return Box::new(ParserAnyMacro {
|
||||
parser: RefCell::new(p),
|
||||
parser: p,
|
||||
|
||||
// Pass along the original expansion site and the name of the macro
|
||||
// so we can print a useful error message if the parse of the expanded
|
||||
|
|
Loading…
Add table
Reference in a new issue