use parse::lexer::Reader;
use parse::lexer::TokenAndSpan;
use parse::obsolete::*;
-use parse::token::{InternedString, can_begin_expr};
-use parse::token::{is_ident, is_ident_or_path, is_plain_ident};
-use parse::token::{keywords, special_idents, token_to_binop};
+use parse::token::InternedString;
+use parse::token::{keywords, special_idents};
use parse::token;
use parse::{new_sub_parser_from_file, ParseSess};
use ptr::P;
}
fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
- is_plain_ident(t) || *t == token::Underscore
+ t.is_plain_ident() || *t == token::Underscore
}
/// Get a token the parser cares about
pub fn commit_stmt(&mut self, edible: &[token::Token], inedible: &[token::Token]) {
if self.last_token
.as_ref()
- .map_or(false, |t| is_ident_or_path(&**t)) {
+ .map_or(false, |t| t.is_ident() || t.is_path()) {
let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
expected.push_all(inedible.as_slice());
self.check_for_erroneous_unit_struct_expecting(
is_present
}
- pub fn is_keyword(&mut self, kw: keywords::Keyword) -> bool {
- token::is_keyword(kw, &self.token)
- }
-
/// If the next token is the given keyword, eat it and return
/// true. Otherwise, return false.
pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool {
- if self.is_keyword(kw) {
+ if self.token.is_keyword(kw) {
self.bump();
true
} else {
/// Signal an error if the given string is a strict keyword
pub fn check_strict_keywords(&mut self) {
- if token::is_strict_keyword(&self.token) {
+ if self.token.is_strict_keyword() {
let token_str = self.this_token_to_string();
let span = self.span;
self.span_err(span,
/// Signal an error if the current token is a reserved keyword
pub fn check_reserved_keywords(&mut self) {
- if token::is_reserved_keyword(&self.token) {
+ if self.token.is_reserved_keyword() {
let token_str = self.this_token_to_string();
self.fatal(format!("`{}` is a reserved keyword",
token_str).as_slice())
pub fn bump(&mut self) {
self.last_span = self.span;
// Stash token for error recovery (sometimes; clone is not necessarily cheap).
- self.last_token = if is_ident_or_path(&self.token) {
+ self.last_token = if self.token.is_ident() || self.token.is_path() {
Some(box self.token.clone())
} else {
None
/// Is the current token one of the keywords that signals a bare function
/// type?
pub fn token_is_bare_fn_keyword(&mut self) -> bool {
- if token::is_keyword(keywords::Fn, &self.token) {
+ if self.token.is_keyword(keywords::Fn) {
return true
}
- if token::is_keyword(keywords::Unsafe, &self.token) ||
- token::is_keyword(keywords::Once, &self.token) {
- return self.look_ahead(1, |t| token::is_keyword(keywords::Fn, t))
+ if self.token.is_keyword(keywords::Unsafe) ||
+ self.token.is_keyword(keywords::Once) {
+ return self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
}
false
/// Is the current token one of the keywords that signals a closure type?
pub fn token_is_closure_keyword(&mut self) -> bool {
- token::is_keyword(keywords::Unsafe, &self.token) ||
- token::is_keyword(keywords::Once, &self.token)
+ self.token.is_keyword(keywords::Unsafe) ||
+ self.token.is_keyword(keywords::Once)
}
/// Is the current token one of the keywords that signals an old-style
/// closure type (with explicit sigil)?
pub fn token_is_old_style_closure_keyword(&mut self) -> bool {
- token::is_keyword(keywords::Unsafe, &self.token) ||
- token::is_keyword(keywords::Once, &self.token) ||
- token::is_keyword(keywords::Fn, &self.token)
- }
-
- pub fn token_is_lifetime(tok: &token::Token) -> bool {
- match *tok {
- token::Lifetime(..) => true,
- _ => false,
- }
+ self.token.is_keyword(keywords::Unsafe) ||
+ self.token.is_keyword(keywords::Once) ||
+ self.token.is_keyword(keywords::Fn)
}
pub fn get_lifetime(&mut self) -> ast::Ident {
pub fn parse_optional_unboxed_closure_kind(&mut self)
-> Option<UnboxedClosureKind> {
if self.token == token::BinOp(token::And) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Mut, t)
- }) &&
- self.look_ahead(2, |t| *t == token::Colon) {
+ self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
+ self.look_ahead(2, |t| *t == token::Colon) {
self.bump();
self.bump();
self.bump();
// BORROWED POINTER
self.expect_and();
self.parse_borrowed_pointee()
- } else if self.is_keyword(keywords::Extern) ||
- self.is_keyword(keywords::Unsafe) ||
+ } else if self.token.is_keyword(keywords::Extern) ||
+ self.token.is_keyword(keywords::Unsafe) ||
self.token_is_bare_fn_keyword() {
// BARE FUNCTION
self.parse_ty_bare_fn()
self.token == token::OrOr ||
(self.token == token::Lt &&
self.look_ahead(1, |t| {
- *t == token::Gt || Parser::token_is_lifetime(t)
+ *t == token::Gt || t.is_lifetime()
})) {
// CLOSURE
item_name: item_name,
}))
} else if self.token == token::ModSep
- || is_ident_or_path(&self.token) {
+ || self.token.is_ident()
+ || self.token.is_path() {
// NAMED TYPE
let mode = if plus_allowed {
LifetimeAndTypesAndBounds
let offset = match self.token {
token::BinOp(token::And) => 1,
token::AndAnd => 1,
- _ if token::is_keyword(keywords::Mut, &self.token) => 1,
+ _ if self.token.is_keyword(keywords::Mut) => 1,
_ => 0
};
}
}
- pub fn token_is_mutability(tok: &token::Token) -> bool {
- token::is_keyword(keywords::Mut, tok) ||
- token::is_keyword(keywords::Const, tok)
- }
-
/// Parse mutability declaration (mut/const/imm)
pub fn parse_mutability(&mut self) -> Mutability {
if self.eat_keyword(keywords::Mut) {
if self.eat_keyword(keywords::While) {
return self.parse_while_expr(None);
}
- if Parser::token_is_lifetime(&self.token) {
+ if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
self.bump();
self.expect(&token::Colon);
}
if self.eat_keyword(keywords::Continue) {
let lo = self.span.lo;
- let ex = if Parser::token_is_lifetime(&self.token) {
+ let ex = if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
self.bump();
ExprAgain(Some(lifetime))
}
if self.eat_keyword(keywords::Return) {
// RETURN expression
- if can_begin_expr(&self.token) {
+ if self.token.can_begin_expr() {
let e = self.parse_expr();
hi = e.span.hi;
ex = ExprRet(Some(e));
}
} else if self.eat_keyword(keywords::Break) {
// BREAK expression
- if Parser::token_is_lifetime(&self.token) {
+ if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
self.bump();
ex = ExprBreak(Some(lifetime));
}
hi = self.span.hi;
} else if self.token == token::ModSep ||
- is_ident(&self.token) &&
- !self.is_keyword(keywords::True) &&
- !self.is_keyword(keywords::False) {
+ self.token.is_ident() &&
+ !self.token.is_keyword(keywords::True) &&
+ !self.token.is_keyword(keywords::False) {
let pth =
self.parse_path(LifetimeAndTypesWithColons).path;
// MACRO INVOCATION expression
self.bump();
- let ket = token::close_delimiter_for(&self.token)
+ let ket = self.token.get_close_delimiter()
.unwrap_or_else(|| {
self.fatal("expected open delimiter")
});
}
}
- match (&self.token, token::close_delimiter_for(&self.token)) {
+ match (&self.token, self.token.get_close_delimiter()) {
(&token::Eof, _) => {
let open_braces = self.open_braces.clone();
for sp in open_braces.iter() {
// the interpolation of Matcher's
maybe_whole!(self, NtMatchers);
let mut name_idx = 0u;
- match token::close_delimiter_for(&self.token) {
+ match self.token.get_close_delimiter() {
Some(other_delimiter) => {
self.bump();
self.parse_matcher_subseq_upto(&mut name_idx, &other_delimiter)
ex = self.mk_unary(UnUniq, e);
}
token::Ident(_, _) => {
- if !self.is_keyword(keywords::Box) {
+ if !self.token.is_keyword(keywords::Box) {
return self.parse_dot_or_call_expr();
}
return lhs;
}
- let cur_opt = token_to_binop(&self.token);
+ let cur_opt = self.token.to_binop();
match cur_opt {
Some(cur_op) => {
let cur_prec = operator_prec(cur_op);
/// Parse an 'if' or 'if let' expression ('if' token already eaten)
pub fn parse_if_expr(&mut self) -> P<Expr> {
- if self.is_keyword(keywords::Let) {
+ if self.token.is_keyword(keywords::Let) {
return self.parse_if_let_expr();
}
let lo = self.last_span.lo;
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> P<Expr> {
- if self.is_keyword(keywords::Let) {
+ if self.token.is_keyword(keywords::Let) {
return self.parse_while_let_expr(opt_ident);
}
let lo = self.last_span.lo;
}
// at this point, token != _, ~, &, &&, (, [
- if (!is_ident_or_path(&self.token) && self.token != token::ModSep)
- || self.is_keyword(keywords::True)
- || self.is_keyword(keywords::False) {
+ if (!(self.token.is_ident() || self.token.is_path())
+ && self.token != token::ModSep)
+ || self.token.is_keyword(keywords::True)
+ || self.token.is_keyword(keywords::False) {
// Parse an expression pattern or exp .. exp.
//
// These expressions are limited to literals (possibly
*t != token::Comma && *t != token::RBracket
}) {
self.bump();
- let end = if is_ident_or_path(&self.token) {
+ let end = if self.token.is_ident() || self.token.is_path() {
let path = self.parse_path(LifetimeAndTypesWithColons)
.path;
let hi = self.span.hi;
self.eat(&token::DotDotDot);
let end = self.parse_expr_res(RESTRICTION_NO_BAR_OP);
pat = PatRange(start, end);
- } else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
+ } else if self.token.is_plain_ident() && !can_be_enum_or_struct {
let id = self.parse_ident();
let id_span = self.last_span;
let pth1 = codemap::Spanned{span:id_span, node: id};
if self.eat(&token::Not) {
// macro invocation
- let ket = token::close_delimiter_for(&self.token)
+ let ket = self.token.get_close_delimiter()
.unwrap_or_else(|| self.fatal("expected open delimiter"));
self.bump();
fn parse_pat_ident(&mut self,
binding_mode: ast::BindingMode)
-> ast::Pat_ {
- if !is_plain_ident(&self.token) {
+ if !self.token.is_plain_ident() {
let span = self.span;
let tok_str = self.this_token_to_string();
self.span_fatal(span,
fn parse_name_and_ty(&mut self, pr: Visibility,
attrs: Vec<Attribute> ) -> StructField {
let lo = self.span.lo;
- if !is_plain_ident(&self.token) {
+ if !self.token.is_plain_ident() {
self.fatal("expected ident");
}
let name = self.parse_ident();
}
let lo = self.span.lo;
- if self.is_keyword(keywords::Let) {
+ if self.token.is_keyword(keywords::Let) {
check_expected_item(self, item_attrs.as_slice());
self.expect_keyword(keywords::Let);
let decl = self.parse_let();
P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
- } else if is_ident(&self.token)
- && !token::is_any_keyword(&self.token)
+ } else if self.token.is_ident()
+ && !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not) {
// it's a macro invocation:
let pth = self.parse_path(NoTypesAllowed).path;
self.bump();
- let id = if token::close_delimiter_for(&self.token).is_some() {
+ let id = if self.token.get_close_delimiter().is_some() {
token::special_idents::invalid // no special identifier
} else {
self.parse_ident()
// check that we're pointing at delimiters (need to check
// again after the `if`, because of `parse_ident`
// consuming more tokens).
- let (bra, ket) = match token::close_delimiter_for(&self.token) {
+ let (bra, ket) = match self.token.get_close_delimiter() {
Some(ket) => (self.token.clone(), ket),
None => {
// we only expect an ident if we didn't parse one
}
fn forbid_lifetime(&mut self) {
- if Parser::token_is_lifetime(&self.token) {
+ if self.token.is_lifetime() {
let span = self.span;
self.span_fatal(span, "lifetime parameters must be declared \
prior to type parameters");
//
// We already know that the current token is `&`.
- if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
+ if this.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
this.bump();
SelfRegion(None, MutImmutable, this.expect_self_ident())
- } else if this.look_ahead(1, |t| Parser::token_is_mutability(t)) &&
- this.look_ahead(2,
- |t| token::is_keyword(keywords::Self,
- t)) {
+ } else if this.look_ahead(1, |t| t.is_mutability()) &&
+ this.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
this.bump();
let mutability = this.parse_mutability();
SelfRegion(None, mutability, this.expect_self_ident())
- } else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
- this.look_ahead(2,
- |t| token::is_keyword(keywords::Self,
- t)) {
+ } else if this.look_ahead(1, |t| t.is_lifetime()) &&
+ this.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
this.bump();
let lifetime = this.parse_lifetime();
SelfRegion(Some(lifetime), MutImmutable, this.expect_self_ident())
- } else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
- this.look_ahead(2, |t| {
- Parser::token_is_mutability(t)
- }) &&
- this.look_ahead(3, |t| token::is_keyword(keywords::Self,
- t)) {
+ } else if this.look_ahead(1, |t| t.is_lifetime()) &&
+ this.look_ahead(2, |t| t.is_mutability()) &&
+ this.look_ahead(3, |t| t.is_keyword(keywords::Self)) {
this.bump();
let lifetime = this.parse_lifetime();
let mutability = this.parse_mutability();
}
token::Tilde => {
// We need to make sure it isn't a type
- if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
+ if self.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
self.bump();
drop(self.expect_self_ident());
let last_span = self.last_span;
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
// emitting cryptic "unexpected token" errors.
self.bump();
- let _mutability = if Parser::token_is_mutability(&self.token) {
+ let _mutability = if self.token.is_mutability() {
self.parse_mutability()
} else {
MutImmutable
} else {
SelfValue(self_ident)
}
- } else if Parser::token_is_mutability(&self.token) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Self, t)
- }) {
+ } else if self.token.is_mutability() &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
mutbl_self = self.parse_mutability();
let self_ident = self.expect_self_ident();
} else {
SelfValue(self_ident)
}
- } else if Parser::token_is_mutability(&self.token) &&
+ } else if self.token.is_mutability() &&
self.look_ahead(1, |t| *t == token::Tilde) &&
- self.look_ahead(2, |t| {
- token::is_keyword(keywords::Self, t)
- }) {
+ self.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
mutbl_self = self.parse_mutability();
self.bump();
drop(self.expect_self_ident());
// code copied from parse_macro_use_or_failure... abstraction!
let (method_, hi, new_attrs) = {
- if !token::is_any_keyword(&self.token)
+ if !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not)
&& (self.look_ahead(2, |t| *t == token::LParen)
|| self.look_ahead(2, |t| *t == token::LBrace)) {
self.expect(&token::Not);
// eat a matched-delimiter token tree:
- let tts = match token::close_delimiter_for(&self.token) {
+ let tts = match self.token.get_close_delimiter() {
Some(ket) => {
self.bump();
self.parse_seq_to_end(&ket,
Some(path)
} else if self.eat_keyword(keywords::As) {
// skip the ident if there is one
- if is_ident(&self.token) { self.bump(); }
+ if self.token.is_ident() { self.bump(); }
self.span_err(span,
format!("expected `;`, found `as`; perhaps you meant \
}
// the rest are all guaranteed to be items:
- if self.is_keyword(keywords::Static) {
+ if self.token.is_keyword(keywords::Static) {
// STATIC ITEM
self.bump();
let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable};
maybe_append(attrs, extra_attrs));
return IoviItem(item);
}
- if self.is_keyword(keywords::Const) {
+ if self.token.is_keyword(keywords::Const) {
// CONST ITEM
self.bump();
if self.eat_keyword(keywords::Mut) {
maybe_append(attrs, extra_attrs));
return IoviItem(item);
}
- if self.is_keyword(keywords::Fn) &&
+ if self.token.is_keyword(keywords::Fn) &&
self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) {
// FUNCTION ITEM
self.bump();
maybe_append(attrs, extra_attrs));
return IoviItem(item);
}
- if self.is_keyword(keywords::Unsafe)
+ if self.token.is_keyword(keywords::Unsafe)
&& self.look_ahead(1u, |t| *t != token::LBrace) {
// UNSAFE FUNCTION ITEM
self.bump();
let visibility = self.parse_visibility();
- if self.is_keyword(keywords::Static) {
+ if self.token.is_keyword(keywords::Static) {
// FOREIGN STATIC ITEM
let item = self.parse_item_foreign_static(visibility, attrs);
return IoviForeignItem(item);
}
- if self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Unsafe) {
+ if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) {
// FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(visibility, attrs);
return IoviForeignItem(item);
lo: BytePos,
visibility: Visibility
) -> ItemOrViewItem {
- if macros_allowed && !token::is_any_keyword(&self.token)
+ if macros_allowed && !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not)
- && (self.look_ahead(2, |t| is_plain_ident(t))
+ && (self.look_ahead(2, |t| t.is_plain_ident())
|| self.look_ahead(2, |t| *t == token::LParen)
|| self.look_ahead(2, |t| *t == token::LBrace)) {
// MACRO INVOCATION ITEM
// a 'special' identifier (like what `macro_rules!` uses)
// is optional. We should eventually unify invoc syntax
// and remove this.
- let id = if is_plain_ident(&self.token) {
+ let id = if self.token.is_plain_ident() {
self.parse_ident()
} else {
token::special_idents::invalid // no special identifier
};
// eat a matched-delimiter token tree:
- let tts = match token::close_delimiter_for(&self.token) {
+ let tts = match self.token.get_close_delimiter() {
Some(ket) => {
self.bump();
self.parse_seq_to_end(&ket,
Eof,
}
+impl Token {
+ /// Returns `true` if the token can appear at the start of an expression.
+ pub fn can_begin_expr(&self) -> bool {
+ match *self {
+ LParen => true,
+ LBrace => true,
+ LBracket => true,
+ Ident(_, _) => true,
+ Underscore => true,
+ Tilde => true,
+ LitByte(_) => true,
+ LitChar(_) => true,
+ LitInteger(_) => true,
+ LitFloat(_) => true,
+ LitStr(_) => true,
+ LitStrRaw(_, _) => true,
+ LitBinary(_) => true,
+ LitBinaryRaw(_, _) => true,
+ Pound => true,
+ At => true,
+ Not => true,
+ BinOp(Minus) => true,
+ BinOp(Star) => true,
+ BinOp(And) => true,
+ BinOp(Or) => true, // in lambda syntax
+ OrOr => true, // in lambda syntax
+ ModSep => true,
+ Interpolated(NtExpr(..)) => true,
+ Interpolated(NtIdent(..)) => true,
+ Interpolated(NtBlock(..)) => true,
+ Interpolated(NtPath(..)) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns the matching close delimiter if this is an open delimiter,
+ /// otherwise `None`.
+ pub fn get_close_delimiter(&self) -> Option<Token> {
+ match *self {
+ LParen => Some(RParen),
+ LBrace => Some(RBrace),
+ LBracket => Some(RBracket),
+ _ => None,
+ }
+ }
+
+ /// Returns `true` if the token is any literal
+ pub fn is_lit(&self) -> bool {
+ match *self {
+ LitByte(_) => true,
+ LitChar(_) => true,
+ LitInteger(_) => true,
+ LitFloat(_) => true,
+ LitStr(_) => true,
+ LitStrRaw(_, _) => true,
+ LitBinary(_) => true,
+ LitBinaryRaw(_, _) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is an identifier.
+ pub fn is_ident(&self) -> bool {
+ match *self {
+ Ident(_, _) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is an interpolated path.
+ pub fn is_path(&self) -> bool {
+ match *self {
+ Interpolated(NtPath(..)) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is a path that is not followed by a `::`
+ /// token.
+ pub fn is_plain_ident(&self) -> bool {
+ match *self {
+ Ident(_, false) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is a lifetime.
+ pub fn is_lifetime(&self) -> bool {
+ match *self {
+ Lifetime(..) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is either the `mut` or `const` keyword.
+ pub fn is_mutability(&self) -> bool {
+ self.is_keyword(keywords::Mut) ||
+ self.is_keyword(keywords::Const)
+ }
+
+ /// Maps a token to its corresponding binary operator.
+ pub fn to_binop(&self) -> Option<ast::BinOp> {
+ match *self {
+ BinOp(Star) => Some(ast::BiMul),
+ BinOp(Slash) => Some(ast::BiDiv),
+ BinOp(Percent) => Some(ast::BiRem),
+ BinOp(Plus) => Some(ast::BiAdd),
+ BinOp(Minus) => Some(ast::BiSub),
+ BinOp(Shl) => Some(ast::BiShl),
+ BinOp(Shr) => Some(ast::BiShr),
+ BinOp(And) => Some(ast::BiBitAnd),
+ BinOp(Caret) => Some(ast::BiBitXor),
+ BinOp(Or) => Some(ast::BiBitOr),
+ Lt => Some(ast::BiLt),
+ Le => Some(ast::BiLe),
+ Ge => Some(ast::BiGe),
+ Gt => Some(ast::BiGt),
+ EqEq => Some(ast::BiEq),
+ Ne => Some(ast::BiNe),
+ AndAnd => Some(ast::BiAnd),
+ OrOr => Some(ast::BiOr),
+ _ => None,
+ }
+ }
+
+ /// Returns `true` if the token is a given keyword, `kw`.
+ pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
+ match *self {
+ Ident(sid, false) => kw.to_name() == sid.name,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is either a special identifier, or a strict
+ /// or reserved keyword.
+ pub fn is_any_keyword(&self) -> bool {
+ match *self {
+ Ident(sid, false) => {
+ let n = sid.name;
+
+ n == SELF_KEYWORD_NAME
+ || n == STATIC_KEYWORD_NAME
+ || n == SUPER_KEYWORD_NAME
+ || STRICT_KEYWORD_START <= n
+ && n <= RESERVED_KEYWORD_FINAL
+ },
+ _ => false
+ }
+ }
+
+ /// Returns `true` if the token may not appear as an identifier.
+ pub fn is_strict_keyword(&self) -> bool {
+ match *self {
+ Ident(sid, false) => {
+ let n = sid.name;
+
+ n == SELF_KEYWORD_NAME
+ || n == STATIC_KEYWORD_NAME
+ || n == SUPER_KEYWORD_NAME
+ || STRICT_KEYWORD_START <= n
+ && n <= STRICT_KEYWORD_FINAL
+ },
+ Ident(sid, true) => {
+ let n = sid.name;
+
+ n != SELF_KEYWORD_NAME
+ && n != SUPER_KEYWORD_NAME
+ && STRICT_KEYWORD_START <= n
+ && n <= STRICT_KEYWORD_FINAL
+ }
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is a keyword that has been reserved for
+ /// possible future use.
+ pub fn is_reserved_keyword(&self) -> bool {
+ match *self {
+ Ident(sid, false) => {
+ let n = sid.name;
+
+ RESERVED_KEYWORD_START <= n
+ && n <= RESERVED_KEYWORD_FINAL
+ },
+ _ => false,
+ }
+ }
+
+ /// Hygienic identifier equality comparison.
+ ///
+ /// See `styntax::ext::mtwt`.
+ pub fn mtwt_eq(&self, other : &Token) -> bool {
+ match (self, other) {
+ (&Ident(id1,_), &Ident(id2,_)) | (&Lifetime(id1), &Lifetime(id2)) =>
+ mtwt::resolve(id1) == mtwt::resolve(id2),
+ _ => *self == *other
+ }
+ }
+}
+
#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash)]
/// For interpolation during macro expansion.
pub enum Nonterminal {
}
}
-pub fn can_begin_expr(t: &Token) -> bool {
- match *t {
- LParen => true,
- LBrace => true,
- LBracket => true,
- Ident(_, _) => true,
- Underscore => true,
- Tilde => true,
- LitByte(_) => true,
- LitChar(_) => true,
- LitInteger(_) => true,
- LitFloat(_) => true,
- LitStr(_) => true,
- LitStrRaw(_, _) => true,
- LitBinary(_) => true,
- LitBinaryRaw(_, _) => true,
- Pound => true,
- At => true,
- Not => true,
- BinOp(Minus) => true,
- BinOp(Star) => true,
- BinOp(And) => true,
- BinOp(Or) => true, // in lambda syntax
- OrOr => true, // in lambda syntax
- ModSep => true,
- Interpolated(NtExpr(..)) => true,
- Interpolated(NtIdent(..)) => true,
- Interpolated(NtBlock(..)) => true,
- Interpolated(NtPath(..)) => true,
- _ => false,
- }
-}
-
-/// Returns the matching close delimiter if this is an open delimiter,
-/// otherwise `None`.
-pub fn close_delimiter_for(t: &Token) -> Option<Token> {
- match *t {
- LParen => Some(RParen),
- LBrace => Some(RBrace),
- LBracket => Some(RBracket),
- _ => None,
- }
-}
-
-pub fn is_lit(t: &Token) -> bool {
- match *t {
- LitByte(_) => true,
- LitChar(_) => true,
- LitInteger(_) => true,
- LitFloat(_) => true,
- LitStr(_) => true,
- LitStrRaw(_, _) => true,
- LitBinary(_) => true,
- LitBinaryRaw(_, _) => true,
- _ => false,
- }
-}
-
-pub fn is_ident(t: &Token) -> bool {
- match *t {
- Ident(_, _) => true,
- _ => false,
- }
-}
-
-pub fn is_ident_or_path(t: &Token) -> bool {
- match *t {
- Ident(_, _) => true,
- Interpolated(NtPath(..)) => true,
- _ => false,
- }
-}
-
-pub fn is_plain_ident(t: &Token) -> bool {
- match *t {
- Ident(_, false) => true,
- _ => false,
- }
-}
-
// Get the first "argument"
macro_rules! first {
( $first:expr, $( $remainder:expr, )* ) => ( $first )
}
}
-/**
- * Maps a token to a record specifying the corresponding binary
- * operator
- */
-pub fn token_to_binop(tok: &Token) -> Option<ast::BinOp> {
- match *tok {
- BinOp(Star) => Some(ast::BiMul),
- BinOp(Slash) => Some(ast::BiDiv),
- BinOp(Percent) => Some(ast::BiRem),
- BinOp(Plus) => Some(ast::BiAdd),
- BinOp(Minus) => Some(ast::BiSub),
- BinOp(Shl) => Some(ast::BiShl),
- BinOp(Shr) => Some(ast::BiShr),
- BinOp(And) => Some(ast::BiBitAnd),
- BinOp(Caret) => Some(ast::BiBitXor),
- BinOp(Or) => Some(ast::BiBitOr),
- Lt => Some(ast::BiLt),
- Le => Some(ast::BiLe),
- Ge => Some(ast::BiGe),
- Gt => Some(ast::BiGt),
- EqEq => Some(ast::BiEq),
- Ne => Some(ast::BiNe),
- AndAnd => Some(ast::BiAnd),
- OrOr => Some(ast::BiOr),
- _ => None
- }
-}
-
// looks like we can get rid of this completely...
pub type IdentInterner = StrInterner;
gensym("mark").uint() as u32
}
-// See the macro above about the types of keywords
-
-pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool {
- match *tok {
- Ident(sid, false) => { kw.to_name() == sid.name }
- _ => { false }
- }
-}
-
-pub fn is_any_keyword(tok: &Token) -> bool {
- match *tok {
- Ident(sid, false) => {
- let n = sid.name;
-
- n == SELF_KEYWORD_NAME
- || n == STATIC_KEYWORD_NAME
- || n == SUPER_KEYWORD_NAME
- || STRICT_KEYWORD_START <= n
- && n <= RESERVED_KEYWORD_FINAL
- },
- _ => false
- }
-}
-
-pub fn is_strict_keyword(tok: &Token) -> bool {
- match *tok {
- Ident(sid, false) => {
- let n = sid.name;
-
- n == SELF_KEYWORD_NAME
- || n == STATIC_KEYWORD_NAME
- || n == SUPER_KEYWORD_NAME
- || STRICT_KEYWORD_START <= n
- && n <= STRICT_KEYWORD_FINAL
- },
- Ident(sid, true) => {
- let n = sid.name;
-
- n != SELF_KEYWORD_NAME
- && n != SUPER_KEYWORD_NAME
- && STRICT_KEYWORD_START <= n
- && n <= STRICT_KEYWORD_FINAL
- }
- _ => false,
- }
-}
-
-pub fn is_reserved_keyword(tok: &Token) -> bool {
- match *tok {
- Ident(sid, false) => {
- let n = sid.name;
-
- RESERVED_KEYWORD_START <= n
- && n <= RESERVED_KEYWORD_FINAL
- },
- _ => false,
- }
-}
-
-pub fn mtwt_token_eq(t1 : &Token, t2 : &Token) -> bool {
- match (t1,t2) {
- (&Ident(id1,_),&Ident(id2,_)) | (&Lifetime(id1),&Lifetime(id2)) =>
- mtwt::resolve(id1) == mtwt::resolve(id2),
- _ => *t1 == *t2
- }
-}
-
-
#[cfg(test)]
mod test {
use super::*;
}
#[test] fn mtwt_token_eq_test() {
- assert!(mtwt_token_eq(&Gt,&Gt));
+ assert!(Gt.mtwt_eq(&Gt));
let a = str_to_ident("bac");
let a1 = mark_ident(a,92);
- assert!(mtwt_token_eq(&Ident(a,true),&Ident(a1,false)));
+ assert!(Ident(a,true).mtwt_eq(&Ident(a1,false)));
}
}