Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factor TokenTrees into their own file in preparation for TokenStreams. #34385

Merged
merged 1 commit into from
Jun 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ use util::nodemap::{NodeMap, FnvHashSet};

use syntax::codemap::{self, mk_sp, respan, Span, Spanned, ExpnId};
use syntax::abi::Abi;
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::attr::{ThinAttributes, ThinAttributesExt};
use syntax::parse::token::{keywords, InternedString};
use syntax::ptr::P;
use syntax::tokenstream::TokenTree;

use std::collections::BTreeMap;
use std::fmt;
Expand Down
192 changes: 1 addition & 191 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@ use attr::{ThinAttributes, HasAttrs};
use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId};
use abi::Abi;
use errors;
use ext::base;
use ext::tt::macro_parser;
use parse::token::{self, keywords, InternedString};
use parse::lexer;
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use print::pprust;
use ptr::P;
use tokenstream::{TokenTree};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make the same comment as last time: is it worth changing this use to a pub use in order to avoid the breakage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, no. Token streams will eventually be added to tokenstream.rs, and hopefully places that currently use tokens trees will generally move to using token streams. Looking forward, procedural macros will shift to work over token streams, and the breakage here is (at least partially) intended to ensure that tokentree actions / procedural macros no longer need to rely on ast.rs in any way.


use std::fmt;
use std::rc::Rc;
Expand Down Expand Up @@ -1097,193 +1094,6 @@ pub enum CaptureBy {
Ref,
}

/// A delimited sequence of token trees
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Delimited {
/// The type of delimiter
pub delim: token::DelimToken,
/// The span covering the opening delimiter
pub open_span: Span,
/// The delimited sequence of token trees
pub tts: Vec<TokenTree>,
/// The span covering the closing delimiter
pub close_span: Span,
}

impl Delimited {
/// Returns the opening delimiter as a token.
pub fn open_token(&self) -> token::Token {
token::OpenDelim(self.delim)
}

/// Returns the closing delimiter as a token.
pub fn close_token(&self) -> token::Token {
token::CloseDelim(self.delim)
}

/// Returns the opening delimiter as a token tree.
pub fn open_tt(&self) -> TokenTree {
TokenTree::Token(self.open_span, self.open_token())
}

/// Returns the closing delimiter as a token tree.
pub fn close_tt(&self) -> TokenTree {
TokenTree::Token(self.close_span, self.close_token())
}
}

/// A sequence of token trees
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct SequenceRepetition {
/// The sequence of token trees
pub tts: Vec<TokenTree>,
/// The optional separator
pub separator: Option<token::Token>,
/// Whether the sequence can be repeated zero (*), or one or more times (+)
pub op: KleeneOp,
/// The number of `MatchNt`s that appear in the sequence (and subsequences)
pub num_captures: usize,
}

/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
/// for token sequences.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum KleeneOp {
ZeroOrMore,
OneOrMore,
}

/// 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(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum TokenTree {
/// A single token
Token(Span, token::Token),
/// A delimited sequence of token trees
Delimited(Span, Rc<Delimited>),

// This only makes sense in MBE macros.

/// A kleene-style repetition sequence with a span
// FIXME(eddyb) #12938 Use DST.
Sequence(Span, Rc<SequenceRepetition>),
}

impl TokenTree {
pub fn len(&self) -> usize {
match *self {
TokenTree::Token(_, token::DocComment(name)) => {
match doc_comment_style(&name.as_str()) {
AttrStyle::Outer => 2,
AttrStyle::Inner => 3
}
}
TokenTree::Token(_, token::SpecialVarNt(..)) => 2,
TokenTree::Token(_, token::MatchNt(..)) => 3,
TokenTree::Delimited(_, ref delimed) => {
delimed.tts.len() + 2
}
TokenTree::Sequence(_, ref seq) => {
seq.tts.len()
}
TokenTree::Token(..) => 0
}
}

pub fn get_tt(&self, index: usize) -> TokenTree {
match (self, index) {
(&TokenTree::Token(sp, token::DocComment(_)), 0) => {
TokenTree::Token(sp, token::Pound)
}
(&TokenTree::Token(sp, token::DocComment(name)), 1)
if doc_comment_style(&name.as_str()) == AttrStyle::Inner => {
TokenTree::Token(sp, token::Not)
}
(&TokenTree::Token(sp, token::DocComment(name)), _) => {
let stripped = strip_doc_comment_decoration(&name.as_str());

// Searches for the occurrences of `"#*` and returns the minimum number of `#`s
// required to wrap the text.
let num_of_hashes = stripped.chars().scan(0, |cnt, x| {
*cnt = if x == '"' {
1
} else if *cnt != 0 && x == '#' {
*cnt + 1
} else {
0
};
Some(*cnt)
}).max().unwrap_or(0);

TokenTree::Delimited(sp, Rc::new(Delimited {
delim: token::Bracket,
open_span: sp,
tts: vec![TokenTree::Token(sp, token::Ident(token::str_to_ident("doc"))),
TokenTree::Token(sp, token::Eq),
TokenTree::Token(sp, token::Literal(
token::StrRaw(token::intern(&stripped), num_of_hashes), None))],
close_span: sp,
}))
}
(&TokenTree::Delimited(_, ref delimed), _) => {
if index == 0 {
return delimed.open_tt();
}
if index == delimed.tts.len() + 1 {
return delimed.close_tt();
}
delimed.tts[index - 1].clone()
}
(&TokenTree::Token(sp, token::SpecialVarNt(var)), _) => {
let v = [TokenTree::Token(sp, token::Dollar),
TokenTree::Token(sp, token::Ident(token::str_to_ident(var.as_str())))];
v[index].clone()
}
(&TokenTree::Token(sp, token::MatchNt(name, kind)), _) => {
let v = [TokenTree::Token(sp, token::SubstNt(name)),
TokenTree::Token(sp, token::Colon),
TokenTree::Token(sp, token::Ident(kind))];
v[index].clone()
}
(&TokenTree::Sequence(_, ref seq), _) => {
seq.tts[index].clone()
}
_ => panic!("Cannot expand a token tree")
}
}

/// Returns the `Span` corresponding to this token tree.
pub fn get_span(&self) -> Span {
match *self {
TokenTree::Token(span, _) => span,
TokenTree::Delimited(span, _) => span,
TokenTree::Sequence(span, _) => span,
}
}

/// Use this token tree as a matcher to parse given tts.
pub fn parse(cx: &base::ExtCtxt, mtch: &[TokenTree], tts: &[TokenTree])
-> macro_parser::NamedParseResult {
// `None` is because we're not interpolating
let arg_rdr = lexer::new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic,
None,
None,
tts.iter().cloned().collect(),
true);
macro_parser::parse(cx.parse_sess(), cx.cfg(), arg_rdr, mtch)
}
}

pub type Mac = Spanned<Mac_>;

/// Represents a macro invocation. The Path indicates which macro
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax/diagnostics/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ use std::collections::BTreeMap;
use std::env;

use ast;
use ast::{Ident, Name, TokenTree};
use ast::{Ident, Name};
use codemap::Span;
use ext::base::{ExtCtxt, MacEager, MacResult};
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
use tokenstream::{TokenTree};
use util::small_vector::SmallVector;

use diagnostics::metadata::output_metadata;
Expand Down
28 changes: 16 additions & 12 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use fold::Folder;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::default::Default;
use tokenstream;


#[derive(Debug,Clone)]
Expand Down Expand Up @@ -163,20 +164,22 @@ pub trait TTMacroExpander {
fn expand<'cx>(&self,
ecx: &'cx mut ExtCtxt,
span: Span,
token_tree: &[ast::TokenTree])
token_tree: &[tokenstream::TokenTree])
-> Box<MacResult+'cx>;
}

pub type MacroExpanderFn =
for<'cx> fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>;
for<'cx> fn(&'cx mut ExtCtxt, Span, &[tokenstream::TokenTree])
-> Box<MacResult+'cx>;

impl<F> TTMacroExpander for F
where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>
where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, &[tokenstream::TokenTree])
-> Box<MacResult+'cx>
{
fn expand<'cx>(&self,
ecx: &'cx mut ExtCtxt,
span: Span,
token_tree: &[ast::TokenTree])
token_tree: &[tokenstream::TokenTree])
-> Box<MacResult+'cx> {
(*self)(ecx, span, token_tree)
}
Expand All @@ -187,22 +190,23 @@ pub trait IdentMacroExpander {
cx: &'cx mut ExtCtxt,
sp: Span,
ident: ast::Ident,
token_tree: Vec<ast::TokenTree> )
token_tree: Vec<tokenstream::TokenTree> )
-> Box<MacResult+'cx>;
}

pub type IdentMacroExpanderFn =
for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<tokenstream::TokenTree>)
-> Box<MacResult+'cx>;

impl<F> IdentMacroExpander for F
where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident,
Vec<ast::TokenTree>) -> Box<MacResult+'cx>
Vec<tokenstream::TokenTree>) -> Box<MacResult+'cx>
{
fn expand<'cx>(&self,
cx: &'cx mut ExtCtxt,
sp: Span,
ident: ast::Ident,
token_tree: Vec<ast::TokenTree> )
token_tree: Vec<tokenstream::TokenTree> )
-> Box<MacResult+'cx>
{
(*self)(cx, sp, ident, token_tree)
Expand Down Expand Up @@ -607,7 +611,7 @@ impl<'a> ExtCtxt<'a> {
expand::MacroExpander::new(self)
}

pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree])
pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree])
-> parser::Parser<'a> {
parse::tts_to_parser(self.parse_sess, tts.to_vec(), self.cfg())
}
Expand Down Expand Up @@ -806,7 +810,7 @@ pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt,
sp: Span,
tts: &[ast::TokenTree],
tts: &[tokenstream::TokenTree],
name: &str) {
if !tts.is_empty() {
cx.span_err(sp, &format!("{} takes no arguments", name));
Expand All @@ -817,7 +821,7 @@ pub fn check_zero_tts(cx: &ExtCtxt,
/// is not a string literal, emit an error and return None.
pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree],
tts: &[tokenstream::TokenTree],
name: &str)
-> Option<String> {
let mut p = cx.new_parser_from_tts(tts);
Expand All @@ -838,7 +842,7 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
/// parsing error, emit a non-fatal error and return None.
pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
tts: &[tokenstream::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
let mut p = cx.new_parser_from_tts(tts);
let mut es = Vec::new();
while p.token != token::Eof {
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use ast::{Block, Crate, DeclKind, PatKind};
use ast::{Local, Ident, Mac_, Name, SpannedIdent};
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
use ast::TokenTree;
use ast;
use ext::mtwt;
use ext::build::AstBuilder;
Expand All @@ -27,6 +26,7 @@ use fold::*;
use util::move_map::MoveMap;
use parse::token::{fresh_mark, fresh_name, intern, keywords};
use ptr::P;
use tokenstream::TokenTree;
use util::small_vector::SmallVector;
use visit;
use visit::Visitor;
Expand Down
Loading