rust/src/libsyntax/parse/obsolete.rs

230 lines
7.3 KiB
Rust
Raw Normal View History

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
Support for parsing unsupported, old syntaxes, for the
purpose of reporting errors. Parsing of these syntaxes
is tested by compile-test/obsolete-syntax.rs.
Obsolete syntax that becomes too hard to parse can be
removed.
*/
use core::prelude::*;
use ast::{expr, expr_lit, lit_nil};
use ast;
2013-01-30 09:56:33 -08:00
use codemap::{span, respan};
use parse::parser::Parser;
use parse::token::Token;
use parse::token;
use core::cmp;
use core::option;
use core::str;
use core::to_bytes;
/// The specific types of unsupported syntax
#[deriving_eq]
pub enum ObsoleteSyntax {
ObsoleteLowerCaseKindBounds,
ObsoleteLet,
ObsoleteFieldTerminator,
ObsoleteStructCtor,
2012-09-10 17:26:20 -07:00
ObsoleteWith,
ObsoleteClassTraits,
ObsoletePrivSection,
ObsoleteModeInFnType,
ObsoleteMoveInit,
ObsoleteBinaryMove,
ObsoleteUnsafeBlock,
ObsoleteUnenforcedBound,
ObsoleteImplSyntax,
ObsoleteTraitBoundSeparator,
2013-02-25 15:54:13 -08:00
ObsoleteMutOwnedPointer,
ObsoleteMutVector,
}
pub impl to_bytes::IterBytes for ObsoleteSyntax {
#[inline(always)]
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
(*self as uint).iter_bytes(lsb0, f);
}
}
pub impl Parser {
/// Reports an obsolete syntax non-fatal error.
fn obsolete(sp: span, kind: ObsoleteSyntax) {
let (kind_str, desc) = match kind {
ObsoleteLowerCaseKindBounds => (
"lower-case kind bounds",
"the `send`, `copy`, `const`, and `owned` \
kinds are represented as traits now, and \
should be camel cased"
),
ObsoleteLet => (
"`let` in field declaration",
"declare fields as `field: Type`"
),
ObsoleteFieldTerminator => (
"field declaration terminated with semicolon",
"fields are now separated by commas"
),
ObsoleteStructCtor => (
"struct constructor",
"structs are now constructed with `MyStruct { foo: val }` \
syntax. Structs with private fields cannot be created \
outside of their defining module"
),
ObsoleteWith => (
"with",
"record update is done with `..`, e.g. \
`MyStruct { foo: bar, .. baz }`"
),
2012-09-10 18:00:03 -07:00
ObsoleteClassTraits => (
"class traits",
"implemented traits are specified on the impl, as in \
`impl foo : bar {`"
),
ObsoletePrivSection => (
"private section",
"the `priv` keyword is applied to individual items, methods, \
and fields"
),
ObsoleteModeInFnType => (
"mode without identifier in fn type",
"to use a (deprecated) mode in a fn type, you should \
give the argument an explicit name (like `&&v: int`)"
),
ObsoleteMoveInit => (
"initializer-by-move",
"Write `let foo = move bar` instead"
),
ObsoleteBinaryMove => (
"binary move",
"Write `foo = move bar` instead"
),
ObsoleteUnsafeBlock => (
"non-standalone unsafe block",
"use an inner `unsafe { ... }` block instead"
),
ObsoleteUnenforcedBound => (
"unenforced type parameter bound",
"use trait bounds on the functions that take the type as \
arguments, not on the types themselves"
),
ObsoleteImplSyntax => (
"colon-separated impl syntax",
"write `impl Trait for Type`"
),
ObsoleteTraitBoundSeparator => (
"space-separated trait bounds",
"write `+` between trait bounds"
),
2013-02-25 15:54:13 -08:00
ObsoleteMutOwnedPointer => (
"const or mutable owned pointer",
2013-02-25 15:54:13 -08:00
"mutability inherits through `~` pointers; place the `~` box
in a mutable location, like a mutable local variable or an \
`@mut` box"
),
ObsoleteMutVector => (
"const or mutable vector",
"mutability inherits through `~` pointers; place the vector \
in a mutable location, like a mutable local variable or an \
`@mut` box"
),
};
self.report(sp, kind, kind_str, desc);
}
// Reports an obsolete syntax non-fatal error, and returns
// a placeholder expression
fn obsolete_expr(sp: span, kind: ObsoleteSyntax) -> @expr {
self.obsolete(sp, kind);
self.mk_expr(sp.lo, sp.hi, expr_lit(@respan(sp, lit_nil)))
}
priv fn report(sp: span, kind: ObsoleteSyntax, kind_str: &str,
desc: &str) {
self.span_err(sp, fmt!("obsolete syntax: %s", kind_str));
if !self.obsolete_set.contains_key(&kind) {
self.sess.span_diagnostic.handler().note(fmt!("%s", desc));
self.obsolete_set.insert(kind, ());
}
}
fn token_is_obsolete_ident(ident: &str, token: Token) -> bool {
match token {
token::IDENT(copy sid, _) => {
str::eq_slice(*self.id_to_str(sid), ident)
}
_ => false
}
}
fn is_obsolete_ident(ident: &str) -> bool {
self.token_is_obsolete_ident(ident, *self.token)
}
fn eat_obsolete_ident(ident: &str) -> bool {
if self.is_obsolete_ident(ident) {
self.bump();
true
} else {
false
}
}
fn try_parse_obsolete_struct_ctor() -> bool {
if self.eat_obsolete_ident("new") {
self.obsolete(*self.last_span, ObsoleteStructCtor);
self.parse_fn_decl(|p| p.parse_arg());
self.parse_block();
true
} else {
false
}
}
fn try_parse_obsolete_with() -> bool {
if *self.token == token::COMMA
&& self.token_is_obsolete_ident("with",
self.look_ahead(1u)) {
self.bump();
}
if self.eat_obsolete_ident("with") {
self.obsolete(*self.last_span, ObsoleteWith);
self.parse_expr();
true
} else {
false
}
}
fn try_parse_obsolete_priv_section() -> bool {
if self.is_keyword(~"priv") && self.look_ahead(1) == token::LBRACE {
self.obsolete(*self.span, ObsoletePrivSection);
self.eat_keyword(~"priv");
self.bump();
while *self.token != token::RBRACE {
self.parse_single_class_item(ast::private);
}
self.bump();
true
} else {
false
}
}
}