1use std::io::prelude::*;
2use std::fs::File;
3use std::io::BufReader;
4use std::str;
5use std::iter::Peekable;
6use std::str::Chars;
7use std::collections::HashMap;
8use std::str::FromStr;
9
10#[derive(Debug)]
11#[derive(PartialEq)]
12pub enum Token {
13 Undetermined,
14 Comment,
15 Keyword,
16 Str,
17 Int,
18 Float,
19 Parenl,
20 Parenr,
21 Bracel,
22 Bracer,
23 Invalid,
24 End,
25}
26
27pub fn tokenize < KeywordTok > ( input: &str, idx: usize, hm: & HashMap< &str, KeywordTok > ) -> ( Token, Option< KeywordTok >, usize, usize, usize ) where KeywordTok : Copy {
28 let mut is_float_signed = false;
29 let mut idxcurrent = idx;
30 let mut idxcurrent_start = idx;
31 let mut iter = (&input[ idx.. ]).chars().peekable(); {
33 let count_skip = skip_white_space( & mut iter );
34 idxcurrent += count_skip;
35 idxcurrent_start += count_skip;
36 }
37
38 let c = match iter.next() {
39 None => return ( Token::End, None, idxcurrent_start, idxcurrent, idxcurrent ),
40 Some(x) => x
41 };
42
43 if c == '{' { return ( Token::Bracel, None, idxcurrent_start, idxcurrent + 1, idxcurrent + 1 )
47 }else if c == '}' {
48 return ( Token::Bracer, None, idxcurrent_start, idxcurrent + 1, idxcurrent + 1 )
49 }else if c == '(' {
50 return ( Token::Parenl, None, idxcurrent_start, idxcurrent + 1, idxcurrent + 1 )
51 }else if c == ')' {
52 return ( Token::Parenr, None, idxcurrent_start, idxcurrent + 1, idxcurrent + 1 )
53 }else if c == '/' { let c_2 = match iter.next() {
55 None => return ( Token::Invalid, None, idxcurrent_start, idxcurrent + 1, idxcurrent + 1 ),
56 Some(x) => x
57 };
58 idxcurrent += 1;
59 if c_2 == '/' {
60 while let Some(x) = iter.next() {
61 if x == '\n' {
62 return tokenize( input, idxcurrent, hm )
66 }
67 idxcurrent += 1;
68 }
69 return tokenize( input, idxcurrent, hm )
72 }else{
73 return ( Token::Invalid, None, idxcurrent_start, idxcurrent, idxcurrent + 1 )
74 }
75 }
76 else if c == '"' { idxcurrent += 1;
78 idxcurrent_start += 1;
79 while let Some(x) = iter.next() {
80 if x == '"' {
81 return ( Token::Str, None, idxcurrent_start, idxcurrent, idxcurrent + 1 )
82 }else if !x.is_alphanumeric() && x != '_' && x != '/'{
83 println!("unexpected character in string: {}", x);
84 return ( Token::Invalid, None, idxcurrent_start, idxcurrent, idxcurrent )
85 }
86 idxcurrent += 1;
87 }
88 return ( Token::Invalid, None, idxcurrent_start, idxcurrent, idxcurrent )
89 }
90 else if c.is_alphabetic() || c == '_' { idxcurrent += 1;
92 while let Some(x) = iter.next() {
93 if !x.is_alphanumeric() && x != '_' {
94 if let Some(mapped_val) = hm.get( &input[ idxcurrent_start..idxcurrent ] ){
95 return ( Token::Keyword, Some(*mapped_val), idxcurrent_start, idxcurrent, idxcurrent )
96 }else{
97 return ( Token::Str, None, idxcurrent_start, idxcurrent, idxcurrent )
98 }
99 }
100 idxcurrent += 1;
101 }
102 if let Some(mapped_val) = hm.get( &input[ idxcurrent_start..idxcurrent ] ){
103 return ( Token::Keyword, Some(*mapped_val), idxcurrent_start, idxcurrent, idxcurrent )
104 }else{
105 return ( Token::Str, None, idxcurrent_start, idxcurrent, idxcurrent )
106 }
107 }
108
109 if c == '-' || c == '+' { idxcurrent += 1;
111 is_float_signed = true;
112 let next_c = iter.peek();
113 match next_c { None => return ( Token::Invalid, None, idxcurrent_start, idxcurrent, idxcurrent ),
115 Some(x) => {
116 if !x.is_numeric() || *x == '.' {
117 return ( Token::Invalid, None, idxcurrent_start, idxcurrent, idxcurrent )
118 }
119 }
120 }
121 }
122
123 let c2 = if is_float_signed { match iter.next() {
125 None => return ( Token::Invalid, None, idxcurrent_start, idxcurrent, idxcurrent ),
126 Some(x) => x
127 }
128 }else{
129 c
130 };
131
132 if c2 == '.' { idxcurrent += 1;
134 while let Some(x) = iter.next() {
135 if !x.is_numeric() {
136 return ( Token::Float, None, idxcurrent_start, idxcurrent, idxcurrent )
138 }
139 idxcurrent += 1;
140 }
141 return ( Token::Str, None, idxcurrent_start, idxcurrent, idxcurrent )
142 }else if c2.is_numeric() { idxcurrent += 1;
144 loop { {
146 let x = match iter.peek() {
147 None => return ( Token::Int, None, idxcurrent_start, idxcurrent, idxcurrent ),
148 Some(x) => x
149 };
150 if !x.is_numeric() {
151 break;
152 }
153 }
154 iter.next();
155 idxcurrent += 1;
156 }
157 { {
159 if *iter.peek().expect("character invalid") != '.' { return ( Token::Int, None, idxcurrent_start, idxcurrent, idxcurrent )
161 }else{
162 { idxcurrent += 1;
164 iter.next();
165 }
166 loop { if let Some(y) = iter.peek() {
168 if !y.is_numeric() {
169 return ( Token::Float, None, idxcurrent_start, idxcurrent, idxcurrent )
170 }
171 } else {
172 break;
173 }
174 iter.next();
175 idxcurrent += 1;
176 }
177 return ( Token::Float, None, idxcurrent_start, idxcurrent, idxcurrent )
178 }
179 }
180 }
181 }
182 ( Token::Undetermined, None, idxcurrent_start, idxcurrent + 1, idxcurrent + 1 )
184}
185
186fn skip_white_space( iter: & mut Peekable<Chars> ) -> usize {
187 let mut skip_count = 0;
188 loop { let is_white_space = match iter.peek() {
190 Some(x) => {
191 let result = if *x == ' ' || *x == '\n' || *x == '\t' || *x == '\r' {
192 skip_count += 1;
193 true
194 }else{
195 false
196 };
197 result
198 },
199 None => return skip_count
200 };
201 if is_white_space {
202 iter.next();
203 }else{
204 break;
205 }
206 }
207 return skip_count
208}
209
210pub fn file_open( file_path: & str ) -> Option<String> {
211 let path = File::open( file_path ).expect("file path open invalid");
212 let mut buf_reader = BufReader::new(path);
213 let mut contents = String::new();
214 match buf_reader.read_to_string( & mut contents ) {
215 Err( e ) => { println!("{}", e ); return None },
216 _ => (),
217 }
218 Some(contents)
219}
220
221pub fn expect_int_array( input: &str, idx: usize, count: usize, arr: & mut [i64] ) -> Result< usize, & 'static str > {
222 let mut idx_current = idx;
223 let hm : HashMap< &str, bool > = HashMap::new();
224 for i in 0..count {
225 let ( tok, _kw_tok, idx_s, idx_e, idx_next ) = tokenize( input, idx_current, & hm );
226 match tok {
227 Token::Int => {
228 arr[i] = i64::from_str( &input[idx_s..idx_e] ).expect("md5common parse int array invalid");
229 idx_current = idx_next;
230 },
231 _ => return Err("unexpected token. int not found.")
232 }
233 }
234 Ok( idx_current )
235}
236
237pub fn expect_float_array( input: &str, idx: usize, count: usize, arr: & mut [f32] ) -> Result< usize, & 'static str > {
238 let mut idx_current = idx;
239 let hm : HashMap< &str, bool > = HashMap::new();
240 for i in 0..count {
241 let ( tok, _kw_tok, idx_s, idx_e, idx_next ) = tokenize( input, idx_current, & hm );
242 match tok {
243 Token::Float => {
244 arr[i] = f32::from_str( &input[idx_s..idx_e] ).expect("md5common parse int array invalid");
245 idx_current = idx_next;
246 },
247 _ => return Err("unexpected token. float not found.")
248 }
249 }
250 Ok( idx_current )
251}
252
253pub fn expect_parenl( input: &str, idx: usize ) -> Result< usize, & 'static str > {
254 let idx_current = idx;
255 let hm : HashMap< &str, bool > = HashMap::new();
256 let ( tok, _kw_tok, _idx_s, _idx_e, idx_next ) = tokenize( input, idx_current, & hm );
257 match tok {
258 Token::Parenl => return Ok( idx_next ),
259 _ => return Err("unexpected token. parenl not found.")
260 }
261}
262
263pub fn expect_parenr( input: &str, idx: usize ) -> Result< usize, & 'static str > {
264 let idx_current = idx;
265 let hm : HashMap< &str, bool > = HashMap::new();
266 let ( tok, _kw_tok, _idx_s, _idx_e, idx_next ) = tokenize( input, idx_current, & hm );
267 match tok {
268 Token::Parenr => return Ok( idx_next ),
269 _ => return Err("unexpected token. parenr not found.")
270 }
271}
272
273pub fn expect_bracel( input: &str, idx: usize ) -> Result< usize, & 'static str > {
274 let idx_current = idx;
275 let hm : HashMap< &str, bool > = HashMap::new();
276 let ( tok, _kw_tok, _idx_s, _idx_e, idx_next ) = tokenize( input, idx_current, & hm );
277 match tok {
278 Token::Bracel => return Ok( idx_next ),
279 _ => return Err("unexpected token. bracel not found.")
280 }
281}
282
283pub fn expect_bracer( input: &str, idx: usize ) -> Result< usize, & 'static str > {
284 let idx_current = idx;
285 let hm : HashMap< &str, bool > = HashMap::new();
286 let ( tok, _kw_tok, _idx_s, _idx_e, idx_next ) = tokenize( input, idx_current, & hm );
287 match tok {
288 Token::Bracer => return Ok( idx_next ),
289 _ => return Err("unexpected token. bracer not found.")
290 }
291}
292
293pub fn expect_str< KeywordTok >( input: &str, idx: usize, hm: & HashMap< &str, KeywordTok >, ret_str: & mut String ) -> Result< usize, & 'static str > where KeywordTok : Copy {
294 let idx_current = idx;
295 let ( tok, _kw_tok, idx_s, idx_e, idx_next ) = tokenize( input, idx_current, & hm );
296 match tok {
297 Token::Str => {
298 *ret_str = input[idx_s..idx_e].to_string();
299 Ok( idx_next )
300 },
301 _ => { Err("unexpected token. string not found.") }
302 }
303}