1 // Copyright 2012 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.
12 Support for parsing unsupported, old syntaxes, for the
13 purpose of reporting errors. Parsing of these syntaxes
14 is tested by compile-test/obsolete-syntax.rs.
16 Obsolete syntax that becomes too hard to parse can be
20 use ast::{expr, expr_lit, lit_nil, Attribute};
22 use codemap::{span, respan};
23 use parse::parser::Parser;
24 use parse::token::{keywords, Token};
30 /// The specific types of unsupported syntax
32 pub enum ObsoleteSyntax {
34 ObsoleteFieldTerminator,
44 ObsoleteUnenforcedBound,
46 ObsoleteMutOwnedPointer,
48 ObsoleteImplVisibility,
50 ObsoleteRecordPattern,
51 ObsoletePostFnTySigil,
56 ObsoleteLifetimeNotation,
57 ObsoleteConstManagedPointer,
61 ObsoleteFixedLengthVectorType,
62 ObsoleteNamedExternModule,
63 ObsoleteMultipleLocalDecl,
64 ObsoleteMutWithMultipleBindings,
65 ObsoleteExternVisibility,
66 ObsoleteUnsafeExternFn,
67 ObsoletePrivVisibility,
70 impl to_bytes::IterBytes for ObsoleteSyntax {
72 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
73 (*self as uint).iter_bytes(lsb0, f)
77 pub trait ParserObsoleteMethods {
78 /// Reports an obsolete syntax non-fatal error.
79 fn obsolete(&self, sp: span, kind: ObsoleteSyntax);
80 // Reports an obsolete syntax non-fatal error, and returns
81 // a placeholder expression
82 fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr;
88 fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool;
89 fn is_obsolete_ident(&self, ident: &str) -> bool;
90 fn eat_obsolete_ident(&self, ident: &str) -> bool;
91 fn try_parse_obsolete_struct_ctor(&self) -> bool;
92 fn try_parse_obsolete_with(&self) -> bool;
93 fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute]) -> bool;
96 impl ParserObsoleteMethods for Parser {
97 /// Reports an obsolete syntax non-fatal error.
98 pub fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
99 let (kind_str, desc) = match kind {
101 "`let` in field declaration",
102 "declare fields as `field: Type`"
104 ObsoleteFieldTerminator => (
105 "field declaration terminated with semicolon",
106 "fields are now separated by commas"
108 ObsoleteStructCtor => (
109 "struct constructor",
110 "structs are now constructed with `MyStruct { foo: val }` \
111 syntax. Structs with private fields cannot be created \
112 outside of their defining module"
116 "record update is done with `..`, e.g. \
117 `MyStruct { foo: bar, .. baz }`"
119 ObsoleteClassTraits => (
121 "implemented traits are specified on the impl, as in \
124 ObsoletePrivSection => (
126 "the `priv` keyword is applied to individual items, methods, \
129 ObsoleteModeInFnType => (
130 "mode without identifier in fn type",
131 "to use a (deprecated) mode in a fn type, you should \
132 give the argument an explicit name (like `&&v: int`)"
134 ObsoleteMoveInit => (
135 "initializer-by-move",
136 "Write `let foo = move bar` instead"
138 ObsoleteBinaryMove => (
140 "Write `foo = move bar` instead"
144 "Use std::util::{swap, replace} instead"
146 ObsoleteUnsafeBlock => (
147 "non-standalone unsafe block",
148 "use an inner `unsafe { ... }` block instead"
150 ObsoleteUnenforcedBound => (
151 "unenforced type parameter bound",
152 "use trait bounds on the functions that take the type as \
153 arguments, not on the types themselves"
155 ObsoleteImplSyntax => (
156 "colon-separated impl syntax",
157 "write `impl Trait for Type`"
159 ObsoleteMutOwnedPointer => (
160 "const or mutable owned pointer",
161 "mutability inherits through `~` pointers; place the `~` box
162 in a mutable location, like a mutable local variable or an \
165 ObsoleteMutVector => (
166 "const or mutable vector",
167 "mutability inherits through `~` pointers; place the vector \
168 in a mutable location, like a mutable local variable or an \
171 ObsoleteImplVisibility => (
172 "visibility-qualified implementation",
173 "`pub` or `priv` goes on individual functions; remove the \
176 ObsoleteRecordType => (
177 "structural record type",
178 "use a structure instead"
180 ObsoleteRecordPattern => (
181 "structural record pattern",
182 "use a structure instead"
184 ObsoletePostFnTySigil => (
185 "fn sigil in postfix position",
186 "Rather than `fn@`, `fn~`, or `fn&`, \
187 write `@fn`, `~fn`, and `&fn` respectively"
189 ObsoleteBareFnType => (
190 "bare function type",
191 "use `&fn` or `extern fn` instead"
193 ObsoleteNewtypeEnum => (
195 "instead of `enum Foo = int`, write `struct Foo(int)`"
198 "obsolete argument mode",
199 "replace `-` or `++` mode with `+`"
201 ObsoleteImplicitSelf => (
203 "use an explicit `self` declaration or declare the method as \
206 ObsoleteLifetimeNotation => (
207 "`/` lifetime notation",
208 "instead of `&foo/bar`, write `&'foo bar`; instead of \
209 `bar/&foo`, write `&bar<'foo>"
211 ObsoleteConstManagedPointer => (
213 "instead of `@const Foo`, write `@Foo`"
219 ObsoleteStaticMethod => (
221 "`static` is superfluous; remove it"
223 ObsoleteConstItem => (
225 "`const` items are now `static` items; replace `const` with \
228 ObsoleteFixedLengthVectorType => (
229 "fixed-length vector notation",
230 "instead of `[T * N]`, write `[T, ..N]`"
232 ObsoleteNamedExternModule => (
233 "named external module",
234 "instead of `extern mod foo { ... }`, write `mod foo { \
237 ObsoleteMultipleLocalDecl => (
238 "declaration of multiple locals at once",
239 "instead of e.g. `let a = 1, b = 2`, write \
240 `let (a, b) = (1, 2)`."
242 ObsoleteMutWithMultipleBindings => (
243 "`mut` with multiple bindings",
244 "use multiple local declarations instead of e.g. `let mut \
247 ObsoleteExternVisibility => (
248 "`pub extern` or `priv extern`",
249 "place the `pub` or `priv` on the individual external items \
252 ObsoleteUnsafeExternFn => (
253 "unsafe external function",
254 "external functions are always unsafe; remove the `unsafe` \
257 ObsoletePrivVisibility => (
258 "`priv` not necessary",
259 "an item without a visibility qualifier is private by default"
263 self.report(sp, kind, kind_str, desc);
266 // Reports an obsolete syntax non-fatal error, and returns
267 // a placeholder expression
268 pub fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr {
269 self.obsolete(sp, kind);
270 self.mk_expr(sp.lo, sp.hi, expr_lit(@respan(sp, lit_nil)))
275 kind: ObsoleteSyntax,
278 self.span_err(sp, fmt!("obsolete syntax: %s", kind_str));
280 if !self.obsolete_set.contains(&kind) {
281 self.sess.span_diagnostic.handler().note(fmt!("%s", desc));
282 self.obsolete_set.insert(kind);
286 pub fn token_is_obsolete_ident(&self, ident: &str, token: &Token)
289 token::IDENT(sid, _) => {
290 str::eq_slice(self.id_to_str(sid), ident)
296 pub fn is_obsolete_ident(&self, ident: &str) -> bool {
297 self.token_is_obsolete_ident(ident, self.token)
300 pub fn eat_obsolete_ident(&self, ident: &str) -> bool {
301 if self.is_obsolete_ident(ident) {
309 pub fn try_parse_obsolete_struct_ctor(&self) -> bool {
310 if self.eat_obsolete_ident("new") {
311 self.obsolete(*self.last_span, ObsoleteStructCtor);
312 self.parse_fn_decl();
320 pub fn try_parse_obsolete_with(&self) -> bool {
321 if *self.token == token::COMMA
322 && self.look_ahead(1,
323 |t| self.token_is_obsolete_ident("with", t)) {
326 if self.eat_obsolete_ident("with") {
327 self.obsolete(*self.last_span, ObsoleteWith);
335 pub fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute])
337 if self.is_keyword(keywords::Priv) &&
338 self.look_ahead(1, |t| *t == token::LBRACE) {
339 self.obsolete(*self.span, ObsoletePrivSection);
340 self.eat_keyword(keywords::Priv);
342 while *self.token != token::RBRACE {
343 self.parse_single_struct_field(ast::private, attrs.to_owned());