1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use {Delimiter, Level, Spacing, Span, __internal};
12 use {Group, Ident, Literal, Punct, TokenTree};
14 use rustc_errors as errors;
16 use syntax::parse::lexer::comments;
17 use syntax::parse::token;
18 use syntax::tokenstream;
19 use syntax_pos::symbol::{keywords, Symbol};
22 pub(crate) fn new_maybe_raw(string: &str, span: Span, is_raw: bool) -> Ident {
23 let sym = Symbol::intern(string);
25 && (sym == keywords::Underscore.name()
26 || ast::Ident::with_empty_ctxt(sym).is_path_segment_keyword())
28 panic!("`{:?}` is not a valid raw identifier", string)
30 Ident { sym, span, is_raw }
35 pub(crate) fn from_internal(delim: token::DelimToken) -> Delimiter {
37 token::Paren => Delimiter::Parenthesis,
38 token::Brace => Delimiter::Brace,
39 token::Bracket => Delimiter::Bracket,
40 token::NoDelim => Delimiter::None,
44 pub(crate) fn to_internal(self) -> token::DelimToken {
46 Delimiter::Parenthesis => token::Paren,
47 Delimiter::Brace => token::Brace,
48 Delimiter::Bracket => token::Bracket,
49 Delimiter::None => token::NoDelim,
55 pub(crate) fn from_internal(
56 stream: tokenstream::TokenStream,
57 stack: &mut Vec<TokenTree>,
59 use syntax::parse::token::*;
61 let (tree, is_joint) = stream.as_tree();
62 let (span, token) = match tree {
63 tokenstream::TokenTree::Token(span, token) => (span, token),
64 tokenstream::TokenTree::Delimited(span, delimed) => {
65 let delimiter = Delimiter::from_internal(delimed.delim);
66 let mut g = Group::new(delimiter, ::TokenStream(delimed.tts.into()));
67 g.set_span(Span(span));
72 let op_kind = if is_joint {
79 let mut x = TokenTree::from($e);
80 x.set_span(Span(span));
86 tt!(Punct::new($a, op_kind))
88 ($a:expr, $b:expr) => {{
89 stack.push(tt!(Punct::new($b, op_kind)));
90 tt!(Punct::new($a, Spacing::Joint))
92 ($a:expr, $b:expr, $c:expr) => {{
93 stack.push(tt!(Punct::new($c, op_kind)));
94 stack.push(tt!(Punct::new($b, Spacing::Joint)));
95 tt!(Punct::new($a, Spacing::Joint))
103 EqEq => op!('=', '='),
107 AndAnd => op!('&', '&'),
108 OrOr => op!('|', '|'),
111 BinOp(Plus) => op!('+'),
112 BinOp(Minus) => op!('-'),
113 BinOp(Star) => op!('*'),
114 BinOp(Slash) => op!('/'),
115 BinOp(Percent) => op!('%'),
116 BinOp(Caret) => op!('^'),
117 BinOp(And) => op!('&'),
118 BinOp(Or) => op!('|'),
119 BinOp(Shl) => op!('<', '<'),
120 BinOp(Shr) => op!('>', '>'),
121 BinOpEq(Plus) => op!('+', '='),
122 BinOpEq(Minus) => op!('-', '='),
123 BinOpEq(Star) => op!('*', '='),
124 BinOpEq(Slash) => op!('/', '='),
125 BinOpEq(Percent) => op!('%', '='),
126 BinOpEq(Caret) => op!('^', '='),
127 BinOpEq(And) => op!('&', '='),
128 BinOpEq(Or) => op!('|', '='),
129 BinOpEq(Shl) => op!('<', '<', '='),
130 BinOpEq(Shr) => op!('>', '>', '='),
133 DotDot => op!('.', '.'),
134 DotDotDot => op!('.', '.', '.'),
135 DotDotEq => op!('.', '.', '='),
139 ModSep => op!(':', ':'),
140 RArrow => op!('-', '>'),
141 LArrow => op!('<', '-'),
142 FatArrow => op!('=', '>'),
145 Question => op!('?'),
146 SingleQuote => op!('\''),
148 Ident(ident, false) => tt!(self::Ident::new(&ident.as_str(), Span(span))),
149 Ident(ident, true) => tt!(self::Ident::new_raw(&ident.as_str(), Span(span))),
151 let ident = ident.without_first_quote();
152 stack.push(tt!(self::Ident::new(&ident.as_str(), Span(span))));
153 tt!(Punct::new('\'', Spacing::Joint))
155 Literal(lit, suffix) => tt!(self::Literal {
161 let style = comments::doc_comment_style(&c.as_str());
162 let stripped = comments::strip_doc_comment_decoration(&c.as_str());
164 tt!(self::Ident::new("doc", Span(span))),
165 tt!(Punct::new('=', Spacing::Alone)),
166 tt!(self::Literal::string(&stripped)),
169 stack.push(tt!(Group::new(Delimiter::Bracket, stream)));
170 if style == ast::AttrStyle::Inner {
171 stack.push(tt!(Punct::new('!', Spacing::Alone)));
173 tt!(Punct::new('#', Spacing::Alone))
176 Interpolated(_) => __internal::with_sess(|sess, _| {
177 let tts = token.interpolated_to_tokenstream(sess, span);
178 tt!(Group::new(Delimiter::None, ::TokenStream(tts)))
181 DotEq => op!('.', '='),
182 OpenDelim(..) | CloseDelim(..) => unreachable!(),
183 Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
187 pub(crate) fn to_internal(self) -> tokenstream::TokenStream {
188 use syntax::parse::token::*;
189 use syntax::tokenstream::{Delimited, TokenTree};
191 let (ch, kind, span) = match self {
192 self::TokenTree::Punct(tt) => (tt.as_char(), tt.spacing(), tt.span()),
193 self::TokenTree::Group(tt) => {
194 return TokenTree::Delimited(
197 delim: tt.delimiter.to_internal(),
198 tts: tt.stream.0.into(),
202 self::TokenTree::Ident(tt) => {
203 let token = Ident(ast::Ident::new(tt.sym, tt.span.0), tt.is_raw);
204 return TokenTree::Token(tt.span.0, token).into();
206 self::TokenTree::Literal(self::Literal {
207 lit: Lit::Integer(ref a),
211 if a.as_str().starts_with("-") =>
213 let minus = BinOp(BinOpToken::Minus);
214 let integer = Symbol::intern(&a.as_str()[1..]);
215 let integer = Literal(Lit::Integer(integer), suffix);
216 let a = TokenTree::Token(span.0, minus);
217 let b = TokenTree::Token(span.0, integer);
218 return vec![a, b].into_iter().collect();
220 self::TokenTree::Literal(self::Literal {
221 lit: Lit::Float(ref a),
225 if a.as_str().starts_with("-") =>
227 let minus = BinOp(BinOpToken::Minus);
228 let float = Symbol::intern(&a.as_str()[1..]);
229 let float = Literal(Lit::Float(float), suffix);
230 let a = TokenTree::Token(span.0, minus);
231 let b = TokenTree::Token(span.0, float);
232 return vec![a, b].into_iter().collect();
234 self::TokenTree::Literal(tt) => {
235 let token = Literal(tt.lit, tt.suffix);
236 return TokenTree::Token(tt.span.0, token).into();
240 let token = match ch {
250 '%' => BinOp(Percent),
266 let tree = TokenTree::Token(span.0, token);
268 Spacing::Alone => tree.into(),
269 Spacing::Joint => tree.joint(),
275 pub(crate) fn to_internal(self) -> errors::Level {
277 Level::Error => errors::Level::Error,
278 Level::Warning => errors::Level::Warning,
279 Level::Note => errors::Level::Note,
280 Level::Help => errors::Level::Help,