// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use core::prelude::*; use ast; use codemap::{BytePos, spanned}; use parse::lexer::reader; use parse::parser::Parser; use parse::token; use core::option::{None, Option, Some}; use core::option; use std::oldmap::HashMap; use opt_vec; use opt_vec::OptVec; // SeqSep : a sequence separator (token) // and whether a trailing separator is allowed. pub struct SeqSep { sep: Option, trailing_sep_allowed: bool } pub fn seq_sep_trailing_disallowed(+t: token::Token) -> SeqSep { SeqSep { sep: Some(t), trailing_sep_allowed: false, } } pub fn seq_sep_trailing_allowed(+t: token::Token) -> SeqSep { SeqSep { sep: Some(t), trailing_sep_allowed: true, } } pub fn seq_sep_none() -> SeqSep { SeqSep { sep: None, trailing_sep_allowed: false, } } pub fn token_to_str(reader: reader, token: &token::Token) -> ~str { token::to_str(reader.interner(), token) } pub impl Parser { fn unexpected_last(t: &token::Token) -> ! { self.span_fatal( *self.last_span, fmt!( "unexpected token: `%s`", token_to_str(self.reader, t) ) ); } fn unexpected() -> ! { self.fatal( fmt!( "unexpected token: `%s`", token_to_str(self.reader, © *self.token) ) ); } // expect and consume the token t. Signal an error if // the next token is not t. fn expect(t: &token::Token) { if *self.token == *t { self.bump(); } else { self.fatal( fmt!( "expected `%s` but found `%s`", token_to_str(self.reader, t), token_to_str(self.reader, © *self.token) ) ) } } fn parse_ident() -> ast::ident { self.check_strict_keywords(); self.check_reserved_keywords(); match *self.token { token::IDENT(i, _) => { self.bump(); i } token::INTERPOLATED(token::nt_ident(*)) => { self.bug( ~"ident interpolation not converted to real token" ); } _ => { self.fatal( fmt!( "expected ident, found `%s`", token_to_str(self.reader, © *self.token) ) ); } } } fn parse_path_list_ident() -> ast::path_list_ident { let lo = self.span.lo; let ident = self.parse_ident(); let hi = self.span.hi; spanned(lo, hi, ast::path_list_ident_ { name: ident, id: self.get_id() }) } fn parse_value_ident() -> ast::ident { return self.parse_ident(); } // consume token 'tok' if it exists. Returns true if the given // token was present, false otherwise. fn eat(tok: &token::Token) -> bool { return if *self.token == *tok { self.bump(); true } else { false }; } // Storing keywords as interned idents instead of strings would be nifty. // A sanity check that the word we are asking for is a known keyword fn require_keyword(word: &~str) { if !self.keywords.contains_key(word) { self.bug(fmt!("unknown keyword: %s", *word)); } } pure fn token_is_word(word: &~str, tok: &token::Token) -> bool { match *tok { token::IDENT(sid, false) => { *self.id_to_str(sid) == *word } _ => { false } } } fn token_is_keyword(word: &~str, tok: &token::Token) -> bool { self.require_keyword(word); self.token_is_word(word, tok) } fn is_keyword(word: &~str) -> bool { self.token_is_keyword(word, © *self.token) } fn is_any_keyword(tok: &token::Token) -> bool { match *tok { token::IDENT(sid, false) => { self.keywords.contains_key(self.id_to_str(sid)) } _ => false } } fn eat_keyword(word: &~str) -> bool { self.require_keyword(word); let is_kw = match *self.token { token::IDENT(sid, false) => *word == *self.id_to_str(sid), _ => false }; if is_kw { self.bump() } is_kw } fn expect_keyword(word: &~str) { self.require_keyword(word); if !self.eat_keyword(word) { self.fatal( fmt!( "expected `%s`, found `%s`", *word, token_to_str(self.reader, © *self.token) ) ); } } fn is_strict_keyword(word: &~str) -> bool { self.strict_keywords.contains_key(word) } fn check_strict_keywords() { match *self.token { token::IDENT(_, false) => { let w = token_to_str(self.reader, © *self.token); self.check_strict_keywords_(&w); } _ => () } } fn check_strict_keywords_(w: &~str) { if self.is_strict_keyword(w) { self.fatal(fmt!("found `%s` in ident position", *w)); } } fn is_reserved_keyword(word: &~str) -> bool { self.reserved_keywords.contains_key(word) } fn check_reserved_keywords() { match *self.token { token::IDENT(_, false) => { let w = token_to_str(self.reader, © *self.token); self.check_reserved_keywords_(&w); } _ => () } } fn check_reserved_keywords_(w: &~str) { if self.is_reserved_keyword(w) { self.fatal(fmt!("`%s` is a reserved keyword", *w)); } } // expect and consume a GT. if a >> is seen, replace it // with a single > and continue. fn expect_gt() { if *self.token == token::GT { self.bump(); } else if *self.token == token::BINOP(token::SHR) { self.replace_token( token::GT, self.span.lo + BytePos(1u), self.span.hi ); } else { let mut s: ~str = ~"expected `"; s += token_to_str(self.reader, &token::GT); s += ~"`, found `"; s += token_to_str(self.reader, © *self.token); s += ~"`"; self.fatal(s); } } // parse a sequence bracketed by '<' and '>', stopping // before the '>'. fn parse_seq_to_before_gt( sep: Option, f: fn(&Parser) -> T ) -> OptVec { let mut first = true; let mut v = opt_vec::Empty; while *self.token != token::GT && *self.token != token::BINOP(token::SHR) { match sep { Some(ref t) => { if first { first = false; } else { self.expect(t); } } _ => () } v.push(f(&self)); } return v; } fn parse_seq_to_gt( sep: Option, f: fn(&Parser) -> T ) -> OptVec { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } // parse a sequence, including the closing delimiter. The function // f must consume tokens until reaching the next separator or // closing bracket. fn parse_seq_to_end( ket: &token::Token, sep: SeqSep, f: fn(&Parser) -> T ) -> ~[T] { let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); val } // parse a sequence, not including the closing delimiter. The function // f must consume tokens until reaching the next separator or // closing bracket. fn parse_seq_to_before_end( ket: &token::Token, sep: SeqSep, f: fn(&Parser) -> T ) -> ~[T] { let mut first: bool = true; let mut v: ~[T] = ~[]; while *self.token != *ket { match sep.sep { Some(ref t) => { if first { first = false; } else { self.expect(t); } } _ => () } if sep.trailing_sep_allowed && *self.token == *ket { break; } v.push(f(&self)); } return v; } // parse a sequence, including the closing delimiter. The function // f must consume tokens until reaching the next separator or // closing bracket. fn parse_unspanned_seq( bra: &token::Token, ket: &token::Token, sep: SeqSep, f: fn(&Parser) -> T ) -> ~[T] { self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); self.bump(); result } // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. fn parse_seq( bra: &token::Token, ket: &token::Token, sep: SeqSep, f: fn(&Parser) -> T ) -> spanned<~[T]> { let lo = self.span.lo; self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); let hi = self.span.hi; self.bump(); spanned(lo, hi, result) } }