rust/src/libsyntax/parse/obsolete.rs

177 lines
5.2 KiB
Rust
Raw Normal View History

/*!
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 codemap::span;
use ast::{expr, expr_lit, lit_nil};
use ast_util::{respan};
use token::token;
/// The specific types of unsupported syntax
pub enum ObsoleteSyntax {
ObsoleteLowerCaseKindBounds,
ObsoleteLet,
ObsoleteFieldTerminator,
ObsoleteStructCtor,
2012-09-10 17:26:20 -07:00
ObsoleteWith,
ObsoleteClassMethod,
ObsoleteClassTraits,
ObsoletePrivSection
}
impl ObsoleteSyntax : cmp::Eq {
pure fn eq(&&other: ObsoleteSyntax) -> bool {
self as uint == other as uint
}
pure fn ne(&&other: ObsoleteSyntax) -> bool {
!self.eq(other)
}
}
impl ObsoleteSyntax: to_bytes::IterBytes {
#[inline(always)]
pure fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as uint).iter_bytes(lsb0, f);
}
}
pub trait ObsoleteReporter {
fn obsolete(sp: span, kind: ObsoleteSyntax);
fn obsolete_expr(sp: span, kind: ObsoleteSyntax) -> @expr;
}
impl parser : ObsoleteReporter {
/// 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 17:26:20 -07:00
ObsoleteClassMethod => (
"class method",
"methods should be defined inside impls"
),
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"
),
};
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, copy 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(copy 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(copy 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(copy 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
}
}
}