scanlex/
token.rs

1use error::ScanError;
2use int::Int;
3
4/// Represents a token returned by `Scanner::get`
5#[derive(Debug)]
6#[derive(PartialEq)]
7pub enum Token {
8  /// a floating-point number, stored as double-precision float
9  Num(f64),
10  /// an integer, stored as eight-byte unsigned
11  Int(i64),
12  /// a quoted string
13  Str(String),
14  /// an identifier \a+[\a\d_]*
15  Iden(String),
16  /// a character (anything not recognized as any of the above
17  Char(char),
18  /// represents an error
19  Error(ScanError),
20  /// end of stream
21  End
22}
23
24fn type_error<T>(t: Token, expected: &str) -> Result<T,ScanError> {
25    Err(ScanError{details: format!("{} expected, got {:?}",expected,t), lineno: 1})
26}
27
28fn int_error<T>(msg: &str, tname: &str) -> Result<T,ScanError> {
29    Err(ScanError{details: format!("integer {} for {}",msg,tname), lineno: 1})
30}
31
32impl Token {
33    /// is this the end token?
34    pub fn finished(&self) -> bool {
35        match *self {
36            Token::End => true,
37            _ => false
38        }
39    }
40
41    /// is this token a float?
42    pub fn is_float(&self) -> bool {
43        match *self {
44            Token::Num(_) => true,
45            _ => false
46        }
47    }
48
49    /// extract the float
50    pub fn to_float(self) -> Option<f64> {
51        match self {
52            Token::Num(n) => Some(n),
53            _ => None
54        }
55    }
56
57    /// extract the float, or complain
58    pub fn to_float_result(self) -> Result<f64,ScanError> {
59        match self {
60            Token::Num(n) => Ok(n),
61            t => type_error(t,"float")
62        }
63    }
64
65    /// is this token an integer?
66    pub fn is_integer(&self) -> bool {
67        match *self {
68            Token::Int(_) => true,
69            _ => false
70        }
71    }
72
73    /// extract the integer
74    pub fn to_integer(self) -> Option<i64> {
75        match self {
76            Token::Int(n) => Some(n),
77            _ => None
78        }
79    }
80
81    /// extract the integer, or complain
82    pub fn to_integer_result(self) -> Result<i64,ScanError> {
83        match self {
84            Token::Int(n) => Ok(n),
85            t => type_error(t,"integer")
86        }
87    }
88
89    /// extract the integer as a particular subtype
90    pub fn to_int_result<I: Int>(self) -> Result<I::Type,ScanError> {
91        let num = self.to_integer_result()?;
92        if num < I::min_value() {
93            return int_error("underflow",I::name());
94        } else
95        if num > I::max_value() {
96            return int_error("overflow",I::name());
97        }
98        Ok(I::cast(num))
99    }
100
101    /// is this token an integer?
102    pub fn is_number(&self) -> bool {
103        match *self {
104            Token::Int(_) | Token::Num(_) => true,
105            _ => false
106        }
107    }
108
109    /// extract the number, not caring about float or integer
110    pub fn to_number(self) -> Option<f64> {
111        match self {
112            Token::Num(n) => Some(n),
113            Token::Int(n) => Some(n as f64),
114            _ => None
115        }
116    }
117
118    /// extract the number, not caring about float or integer, or complain
119    pub fn to_number_result(self) -> Result<f64,ScanError> {
120        match self {
121            Token::Num(n) => Ok(n),
122            Token::Int(n) => Ok(n as f64),
123            t => type_error(t,"number")
124        }
125    }
126
127    /// is this token a string?
128    pub fn is_string(&self) -> bool {
129        match *self {
130            Token::Str(_) => true,
131            _ => false
132        }
133    }
134
135    /// extract the string
136    pub fn to_string(self) -> Option<String> {
137        match self {
138            Token::Str(s) => Some(s),
139            _ => None
140        }
141    }
142
143    /// extract a reference the string
144    pub fn as_string(&self) -> Option<&str> {
145        match *self {
146            Token::Str(ref s) => Some(s.as_str()),
147            _ => None
148        }
149    }
150
151    /// extract the string, or complain
152    pub fn to_string_result(self) -> Result<String,ScanError> {
153        match self {
154            Token::Str(s) => Ok(s),
155            t => type_error(t,"string")
156        }
157    }
158
159    /// is this token an identifier?
160    pub fn is_iden(&self) -> bool {
161        match *self {
162            Token::Iden(_) => true,
163            _ => false
164        }
165    }
166
167    /// extract the identifier
168    pub fn to_iden(self) -> Option<String> {
169        match self {
170            Token::Iden(n) => Some(n),
171            _ => None
172        }
173    }
174
175    /// extract a reference to the identifier
176    pub fn as_iden(&self) -> Option<&str> {
177        match *self {
178            Token::Iden(ref n) => Some(n.as_str()),
179            _ => None
180        }
181    }
182
183
184    /// extract the identifier, or complain
185    pub fn to_iden_result(self) -> Result<String,ScanError> {
186        match self {
187            Token::Iden(n) => Ok(n),
188            t => type_error(t,"iden")
189        }
190    }
191
192    /// is this token a character?
193    pub fn is_char(&self) -> bool {
194        match *self {
195            Token::Char(_) => true,
196            _ => false
197        }
198    }
199
200    /// extract the character
201    pub fn to_char(self) -> Option<char> {
202        match self {
203            Token::Char(c) => Some(c),
204            _ => None
205        }
206    }
207
208    /// extract the character
209    pub fn as_char(&self) -> Option<char> {
210        match *self {
211            Token::Char(c) => Some(c),
212            _ => None
213        }
214    }
215
216    /// extract the character, or complain
217    pub fn to_char_result(self) -> Result<char,ScanError> {
218        match self {
219            Token::Char(c) => Ok(c),
220            t => type_error(t,"char")
221        }
222    }
223
224    /// is this token an error?
225    pub fn is_error(&self) -> bool {
226        match *self {
227            Token::Error(_) => true,
228            _ => false
229        }
230    }
231
232    /// extract the error
233    pub fn to_error(self) -> Option<ScanError> {
234        match self {
235            Token::Error(e) => Some(e),
236            _ => None
237        }
238    }
239
240}