1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
extern crate csv;
use std::error::Error;
use std::fmt::Debug;

#[derive(Debug)]
pub struct Config {
	input: String,
	states: Vec<u32>,
	inputs: Vec<char>,
	transition_table: Vec<Vec<u32>>,
	start_state: u32,
	final_states: Vec<u32>,
}

impl Config {
	pub fn new (args: Vec<String>) -> Result<Config, Box<Error>> {

		let input = args[1].to_string();
		let mut inputs = Vec::new();
		let mut states = Vec::new();
		let start_state: u32 = args[2].parse()?;
		let mut final_states = Vec::new(); 
		let final_states_path = args[4].to_string();
		let mut transition_table: Vec<Vec<u32>> = Vec::new();
		let transition_table_path = args[3].to_string();
		
		//Read final_states from csv file
		let mut final_states_reader = csv::ReaderBuilder::new()
			.has_headers(false)
			.from_path(final_states_path)?;
		for record in final_states_reader.records() {
			for final_state in record?.iter() {
				final_states.push(final_state.trim().parse()?);
			}
		}
		//println!("final_states : {:?}", final_states);

		let mut transition_table_reader = csv::ReaderBuilder::new()
			.has_headers(true)
			.from_path(transition_table_path)?;

		//Read inputs from transition_table csv file
		for field in transition_table_reader.headers()?.iter().skip(1) {
			let input: char = field.trim().parse()?;
			inputs.push(input)
		}
		//println!("inputs : {:?}", inputs);

		//Read states and transition_table from transition_table csv file
		for record in transition_table_reader.records() {
			let mut row = Vec::new();
			for delta in record?.iter() {
				row.push(delta.trim().parse()?)
			}
			states.push(row.remove(0));
			transition_table.push(row.clone());
		}

		//println!("states : {:?}", states);
		//println!("transition_table : {:?}", transition_table);

		Ok(Config{ input,states, inputs, transition_table, start_state, final_states })
	}
}

pub fn run(config: &Config) -> Result<bool, Box<Error>> {
	let mut present_state: &u32 = &config.start_state;
	for symbol in config.input.chars() {
		let input_index = find(symbol, &config.inputs).unwrap_or_else(|| { panic!("Wrong inputs") });
		let state_index = find(*present_state, &config.states).unwrap_or_else(|| { panic!("Wrong states"); });
		present_state = config.transition_table.get(state_index).unwrap().get(input_index).unwrap();
	}
	Ok(config.final_states.contains(present_state))
}

fn find<T: PartialEq+Debug>(key: T, vector: &Vec<T>) -> Option<usize> {
	for (i, element) in vector.iter().enumerate() {

		if key == *element {
			return Some(i);
		}
	}
	None
}