1 // Copyright 2015 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 // ignore-cross-compile
13 #![feature(rustc_private)]
21 use syntax
::parse
::{ParseSess,filemap_to_tts, PResult}
;
22 use syntax
::parse
::new_parser_from_source_str
;
23 use syntax
::parse
::parser
::Parser
;
24 use syntax
::parse
::token
;
26 use syntax
::str::char_at
;
27 use syntax
::parse
::attr
::*;
28 use syntax
::print
::pprust
;
31 // Copied out of syntax::util::parser_testing
33 pub fn string_to_parser
<'a
>(ps
: &'a ParseSess
, source_str
: String
) -> Parser
<'a
> {
34 new_parser_from_source_str(ps
,
36 "bogofile".to_string(),
40 fn with_error_checking_parse
<'a
, T
, F
>(s
: String
, ps
: &'a ParseSess
, f
: F
) -> PResult
<'a
, T
> where
41 F
: FnOnce(&mut Parser
<'a
>) -> PResult
<'a
, T
>,
43 let mut p
= string_to_parser(&ps
, s
);
46 if ps
.span_diagnostic
.has_errors() || p
.token
!= token
::Eof
{
47 if let Err(mut e
) = x
{
50 return Err(p
.fatal("parse error"));
56 fn expr
<'a
>(s
: &str, ps
: &'a ParseSess
) -> PResult
<'a
, P
<ast
::Expr
>> {
57 with_error_checking_parse(s
.to_string(), ps
, |p
| {
62 fn stmt
<'a
>(s
: &str, ps
: &'a ParseSess
) -> PResult
<'a
, P
<ast
::Stmt
>> {
63 with_error_checking_parse(s
.to_string(), ps
, |p
| {
64 p
.parse_stmt().map(|s
| s
.unwrap())
68 fn attr
<'a
>(s
: &str, ps
: &'a ParseSess
) -> PResult
<'a
, ast
::Attribute
> {
69 with_error_checking_parse(s
.to_string(), ps
, |p
| {
70 p
.parse_attribute(true)
74 fn str_compare
<T
, F
: Fn(&T
) -> String
>(e
: &str, expected
: &[T
], actual
: &[T
], f
: F
) {
75 let expected
: Vec
<_
> = expected
.iter().map(|e
| f(e
)).collect();
76 let actual
: Vec
<_
> = actual
.iter().map(|e
| f(e
)).collect();
78 if expected
!= actual
{
79 panic
!("parsed `{}` as {:?}, expected {:?}", e
, actual
, expected
);
83 fn check_expr_attrs(es
: &str, expected
: &[&str]) {
84 let ps
= ParseSess
::new();
85 let e
= expr(es
, &ps
).expect("parse error");
86 let actual
= &e
.attrs
;
88 &expected
.iter().map(|r
| attr(r
, &ps
).unwrap()).collect
::<Vec
<_
>>(),
89 actual
.as_attr_slice(),
90 pprust
::attribute_to_string
);
93 fn check_stmt_attrs(es
: &str, expected
: &[&str]) {
94 let ps
= ParseSess
::new();
95 let e
= stmt(es
, &ps
).expect("parse error");
96 let actual
= e
.node
.attrs();
98 &expected
.iter().map(|r
| attr(r
, &ps
).unwrap()).collect
::<Vec
<_
>>(),
100 pprust
::attribute_to_string
);
103 fn reject_expr_parse(es
: &str) {
104 let ps
= ParseSess
::new();
105 match expr(es
, &ps
) {
106 Ok(_
) => panic
!("parser did not reject `{}`", es
),
107 Err(mut e
) => e
.cancel(),
111 fn reject_stmt_parse(es
: &str) {
112 let ps
= ParseSess
::new();
113 match stmt(es
, &ps
) {
114 Ok(_
) => panic
!("parser did not reject `{}`", es
),
115 Err(mut e
) => e
.cancel(),
120 let both
= &["#[attr]", "#![attr]"];
121 let outer
= &["#[attr]"];
124 check_expr_attrs("#[attr] box 0", outer
);
125 reject_expr_parse("box #![attr] 0");
127 check_expr_attrs("#[attr] 0 <- #[attr] 0", none
);
128 check_expr_attrs("#[attr] (0 <- 0)", outer
);
129 reject_expr_parse("0 #[attr] <- 0");
130 reject_expr_parse("0 <- #![attr] 0");
132 check_expr_attrs("in #[attr] 0 {#[attr] 0}", none
);
133 check_expr_attrs("#[attr] (in 0 {0})", outer
);
134 reject_expr_parse("in 0 #[attr] {0}");
135 reject_expr_parse("in 0 {#![attr] 0}");
137 check_expr_attrs("#[attr] [#![attr]]", both
);
138 check_expr_attrs("#[attr] [#![attr] 0]", both
);
139 check_expr_attrs("#[attr] [#![attr] 0; 0]", both
);
140 check_expr_attrs("#[attr] [#![attr] 0, 0, 0]", both
);
141 reject_expr_parse("[#[attr]]");
143 check_expr_attrs("#[attr] foo()", outer
);
144 check_expr_attrs("#[attr] x.foo()", outer
);
145 reject_expr_parse("foo#[attr]()");
146 reject_expr_parse("foo(#![attr])");
147 reject_expr_parse("x.foo(#![attr])");
148 reject_expr_parse("x.#[attr]foo()");
149 reject_expr_parse("x.#![attr]foo()");
151 check_expr_attrs("#[attr] (#![attr])", both
);
152 check_expr_attrs("#[attr] (#![attr] #[attr] 0,)", both
);
153 check_expr_attrs("#[attr] (#![attr] #[attr] 0, 0)", both
);
155 check_expr_attrs("#[attr] 0 + #[attr] 0", none
);
156 check_expr_attrs("#[attr] 0 / #[attr] 0", none
);
157 check_expr_attrs("#[attr] 0 & #[attr] 0", none
);
158 check_expr_attrs("#[attr] 0 % #[attr] 0", none
);
159 check_expr_attrs("#[attr] (0 + 0)", outer
);
160 reject_expr_parse("0 + #![attr] 0");
162 check_expr_attrs("#[attr] !0", outer
);
163 check_expr_attrs("#[attr] -0", outer
);
164 reject_expr_parse("!#![attr] 0");
165 reject_expr_parse("-#![attr] 0");
167 check_expr_attrs("#[attr] false", outer
);
168 check_expr_attrs("#[attr] 0", outer
);
169 check_expr_attrs("#[attr] 'c'", outer
);
171 check_expr_attrs("#[attr] x as Y", none
);
172 check_expr_attrs("#[attr] (x as Y)", outer
);
173 reject_expr_parse("x #![attr] as Y");
175 reject_expr_parse("#[attr] if false {}");
176 reject_expr_parse("if false #[attr] {}");
177 reject_expr_parse("if false {#![attr]}");
178 reject_expr_parse("if false {} #[attr] else {}");
179 reject_expr_parse("if false {} else #[attr] {}");
180 reject_expr_parse("if false {} else {#![attr]}");
181 reject_expr_parse("if false {} else #[attr] if true {}");
182 reject_expr_parse("if false {} else if true #[attr] {}");
183 reject_expr_parse("if false {} else if true {#![attr]}");
185 reject_expr_parse("#[attr] if let Some(false) = false {}");
186 reject_expr_parse("if let Some(false) = false #[attr] {}");
187 reject_expr_parse("if let Some(false) = false {#![attr]}");
188 reject_expr_parse("if let Some(false) = false {} #[attr] else {}");
189 reject_expr_parse("if let Some(false) = false {} else #[attr] {}");
190 reject_expr_parse("if let Some(false) = false {} else {#![attr]}");
191 reject_expr_parse("if let Some(false) = false {} else #[attr] if let Some(false) = true {}");
192 reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true #[attr] {}");
193 reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true {#![attr]}");
195 check_expr_attrs("#[attr] while true {#![attr]}", both
);
197 check_expr_attrs("#[attr] while let Some(false) = true {#![attr]}", both
);
199 check_expr_attrs("#[attr] for x in y {#![attr]}", both
);
201 check_expr_attrs("#[attr] loop {#![attr]}", both
);
203 check_expr_attrs("#[attr] match true {#![attr] #[attr] _ => false}", both
);
205 check_expr_attrs("#[attr] || #[attr] foo", outer
);
206 check_expr_attrs("#[attr] move || #[attr] foo", outer
);
207 check_expr_attrs("#[attr] || #[attr] { #![attr] foo }", outer
);
208 check_expr_attrs("#[attr] move || #[attr] { #![attr] foo }", outer
);
209 check_expr_attrs("#[attr] || { #![attr] foo }", outer
);
210 check_expr_attrs("#[attr] move || { #![attr] foo }", outer
);
211 reject_expr_parse("|| #![attr] foo");
212 reject_expr_parse("move || #![attr] foo");
213 reject_expr_parse("|| #![attr] {foo}");
214 reject_expr_parse("move || #![attr] {foo}");
216 check_expr_attrs("#[attr] { #![attr] }", both
);
217 check_expr_attrs("#[attr] { #![attr] let _ = (); }", both
);
218 check_expr_attrs("#[attr] { #![attr] let _ = (); foo }", both
);
220 check_expr_attrs("#[attr] x = y", none
);
221 check_expr_attrs("#[attr] (x = y)", outer
);
223 check_expr_attrs("#[attr] x += y", none
);
224 check_expr_attrs("#[attr] (x += y)", outer
);
226 check_expr_attrs("#[attr] foo.bar", outer
);
227 check_expr_attrs("(#[attr] foo).bar", none
);
229 check_expr_attrs("#[attr] foo.0", outer
);
230 check_expr_attrs("(#[attr] foo).0", none
);
232 check_expr_attrs("#[attr] foo[bar]", outer
);
233 check_expr_attrs("(#[attr] foo)[bar]", none
);
235 check_expr_attrs("#[attr] 0..#[attr] 0", none
);
236 check_expr_attrs("#[attr] 0..", none
);
237 reject_expr_parse("#[attr] ..#[attr] 0");
238 reject_expr_parse("#[attr] ..");
240 check_expr_attrs("#[attr] (0..0)", outer
);
241 check_expr_attrs("#[attr] (0..)", outer
);
242 check_expr_attrs("#[attr] (..0)", outer
);
243 check_expr_attrs("#[attr] (..)", outer
);
245 check_expr_attrs("#[attr] foo::bar::baz", outer
);
247 check_expr_attrs("#[attr] &0", outer
);
248 check_expr_attrs("#[attr] &mut 0", outer
);
249 check_expr_attrs("#[attr] & #[attr] 0", outer
);
250 check_expr_attrs("#[attr] &mut #[attr] 0", outer
);
251 reject_expr_parse("#[attr] &#![attr] 0");
252 reject_expr_parse("#[attr] &mut #![attr] 0");
254 check_expr_attrs("#[attr] break", outer
);
255 check_expr_attrs("#[attr] continue", outer
);
256 check_expr_attrs("#[attr] return", outer
);
258 check_expr_attrs("#[attr] foo!()", outer
);
259 check_expr_attrs("#[attr] foo!(#![attr])", outer
);
260 check_expr_attrs("#[attr] foo![]", outer
);
261 check_expr_attrs("#[attr] foo![#![attr]]", outer
);
262 check_expr_attrs("#[attr] foo!{}", outer
);
263 check_expr_attrs("#[attr] foo!{#![attr]}", outer
);
265 check_expr_attrs("#[attr] Foo { #![attr] bar: baz }", both
);
266 check_expr_attrs("#[attr] Foo { #![attr] ..foo }", both
);
267 check_expr_attrs("#[attr] Foo { #![attr] bar: baz, ..foo }", both
);
269 check_expr_attrs("#[attr] (#![attr] 0)", both
);
271 // Look at statements in their natural habitat...
280 check_stmt_attrs("#[attr] let _ = 0", outer
);
281 check_stmt_attrs("#[attr] 0", outer
);
282 check_stmt_attrs("#[attr] {#![attr]}", both
);
283 check_stmt_attrs("#[attr] foo!()", outer
);
284 check_stmt_attrs("#[attr] foo![]", outer
);
285 check_stmt_attrs("#[attr] foo!{}", outer
);
287 reject_stmt_parse("#[attr] #![attr] let _ = 0");
288 reject_stmt_parse("#[attr] #![attr] 0");
289 reject_stmt_parse("#[attr] #![attr] foo!()");
290 reject_stmt_parse("#[attr] #![attr] foo![]");
291 reject_stmt_parse("#[attr] #![attr] foo!{}");
293 // FIXME: Allow attributes in pattern constexprs?
294 // would require parens in patterns to allow disambiguation...
296 reject_expr_parse("match 0 {
299 reject_expr_parse("match 0 {
300 0...#[attr] -10 => ()
302 reject_expr_parse("match 0 {
303 0...-#[attr] 10 => ()
305 reject_expr_parse("match 0 {
306 0...#[attr] FOO => ()
309 // make sure we don't catch this bug again...