| /*! |
| 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, |
| ObsoleteWith, |
| ObsoleteClassMethod, |
| ObsoleteClassTraits, |
| ObsoletePrivSection, |
| ObsoleteModeInFnType, |
| ObsoleteByMutRefMode |
| } |
| |
| 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 }`" |
| ), |
| ObsoleteClassMethod => ( |
| "class method", |
| "methods should be defined inside impls" |
| ), |
| 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`)" |
| ), |
| ObsoleteByMutRefMode => ( |
| "by-mutable-reference mode", |
| "Declare an argument of type &mut T instead" |
| ), |
| }; |
| |
| 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 |
| } |
| } |
| } |
| |