use error::ScanError;
use int::Int;
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Token {
Num(f64),
Int(i64),
Str(String),
Iden(String),
Char(char),
Error(ScanError),
End
}
fn type_error<T>(t: Token, expected: &str) -> Result<T,ScanError> {
Err(ScanError{details: format!("{} expected, got {:?}",expected,t), lineno: 1})
}
fn int_error<T>(msg: &str, tname: &str) -> Result<T,ScanError> {
Err(ScanError{details: format!("integer {} for {}",msg,tname), lineno: 1})
}
impl Token {
pub fn finished(&self) -> bool {
match *self {
Token::End => true,
_ => false
}
}
pub fn is_float(&self) -> bool {
match *self {
Token::Num(_) => true,
_ => false
}
}
pub fn to_float(self) -> Option<f64> {
match self {
Token::Num(n) => Some(n),
_ => None
}
}
pub fn to_float_result(self) -> Result<f64,ScanError> {
match self {
Token::Num(n) => Ok(n),
t => type_error(t,"float")
}
}
pub fn is_integer(&self) -> bool {
match *self {
Token::Int(_) => true,
_ => false
}
}
pub fn to_integer(self) -> Option<i64> {
match self {
Token::Int(n) => Some(n),
_ => None
}
}
pub fn to_integer_result(self) -> Result<i64,ScanError> {
match self {
Token::Int(n) => Ok(n),
t => type_error(t,"integer")
}
}
pub fn to_int_result<I: Int>(self) -> Result<I::Type,ScanError> {
let num = self.to_integer_result()?;
if num < I::min_value() {
return int_error("underflow",I::name());
} else
if num > I::max_value() {
return int_error("overflow",I::name());
}
Ok(I::cast(num))
}
pub fn is_number(&self) -> bool {
match *self {
Token::Int(_) | Token::Num(_) => true,
_ => false
}
}
pub fn to_number(self) -> Option<f64> {
match self {
Token::Num(n) => Some(n),
Token::Int(n) => Some(n as f64),
_ => None
}
}
pub fn to_number_result(self) -> Result<f64,ScanError> {
match self {
Token::Num(n) => Ok(n),
Token::Int(n) => Ok(n as f64),
t => type_error(t,"number")
}
}
pub fn is_string(&self) -> bool {
match *self {
Token::Str(_) => true,
_ => false
}
}
pub fn to_string(self) -> Option<String> {
match self {
Token::Str(s) => Some(s),
_ => None
}
}
pub fn as_string(&self) -> Option<&str> {
match *self {
Token::Str(ref s) => Some(s.as_str()),
_ => None
}
}
pub fn to_string_result(self) -> Result<String,ScanError> {
match self {
Token::Str(s) => Ok(s),
t => type_error(t,"string")
}
}
pub fn is_iden(&self) -> bool {
match *self {
Token::Iden(_) => true,
_ => false
}
}
pub fn to_iden(self) -> Option<String> {
match self {
Token::Iden(n) => Some(n),
_ => None
}
}
pub fn as_iden(&self) -> Option<&str> {
match *self {
Token::Iden(ref n) => Some(n.as_str()),
_ => None
}
}
pub fn to_iden_result(self) -> Result<String,ScanError> {
match self {
Token::Iden(n) => Ok(n),
t => type_error(t,"iden")
}
}
pub fn is_char(&self) -> bool {
match *self {
Token::Char(_) => true,
_ => false
}
}
pub fn to_char(self) -> Option<char> {
match self {
Token::Char(c) => Some(c),
_ => None
}
}
pub fn as_char(&self) -> Option<char> {
match *self {
Token::Char(c) => Some(c),
_ => None
}
}
pub fn to_char_result(self) -> Result<char,ScanError> {
match self {
Token::Char(c) => Ok(c),
t => type_error(t,"char")
}
}
pub fn is_error(&self) -> bool {
match *self {
Token::Error(_) => true,
_ => false
}
}
pub fn to_error(self) -> Option<ScanError> {
match self {
Token::Error(e) => Some(e),
_ => None
}
}
}