frostwalker/
validator.rs

1//! Module containing the validator which makes sure that a Token list is correct.
2use super::{Token, Class};
3
4#[derive(Debug)]
5#[derive(PartialEq)]
6enum ExpectedClass {
7	IDENTIFIER,
8	EQUALS,
9	NEWLINE,
10	LITERALORSEPARATOR,
11	LITERAL,
12	SEPARATOR,
13}
14
15/// Borrows a token list and either outputs None, meaning no error, or Some(String) with an error message inside.
16///
17/// ```
18/// use frostwalker::{validator, Class, Token};
19///
20/// let ident = Token { class: Class::IDENTIFIER, value: Some("friend".to_string()) };
21/// let equals = Token { class: Class::EQUALS, value: None };
22/// let val = Token { class: Class::LITERAL, value: Some("ferris".to_string()) };
23///
24/// assert_eq!(validator::validate(&vec![ident, equals, val]), None);
25/// ```
26pub fn validate(tree: &Vec<Token>) -> Option<String> {
27	let mut expected_token: ExpectedClass = ExpectedClass::IDENTIFIER;
28	let mut i = 0;
29	let mut line = 1;
30	while i < tree.len() {
31
32		if tree[i].class == Class::NEWLINE && i == 0 {
33			i = i + 1;
34			line = line + 1;
35			continue;
36		}
37
38		if tree[i].class == Class::NEWLINE && expected_token == ExpectedClass::NEWLINE {
39			i = i + 1;
40			line = line + 1;
41			expected_token = ExpectedClass::IDENTIFIER;
42			continue;
43		}
44
45		if tree[i].class == Class::IDENTIFIER && expected_token == ExpectedClass::IDENTIFIER {
46			i = i + 1;
47			if tree.len() - i == 0 {
48				return Some(format!("Key left undefined on line {}.", line));
49			}
50			expected_token = ExpectedClass::EQUALS;
51			continue;
52		}
53
54		if tree[i].class == Class::EQUALS && expected_token == ExpectedClass::EQUALS {
55			i = i + 1;
56			expected_token = ExpectedClass::LITERALORSEPARATOR;
57			if tree.len() - i == 0 {
58				return Some(format!("Key left undefined on line {}.", line));
59			}
60			continue;
61		}
62
63		if (tree[i].class == Class::LITERAL || tree[i].class == Class::BOOLEAN) && expected_token == ExpectedClass::LITERALORSEPARATOR {
64			i = i + 1;
65			expected_token = ExpectedClass::NEWLINE;
66			continue;
67		}
68
69		if (tree[i].class == Class::LITERAL || tree[i].class == Class::BOOLEAN) && expected_token == ExpectedClass::LITERAL {
70			i = i + 1;
71			expected_token = ExpectedClass::SEPARATOR;
72			continue;
73		}
74
75		if tree[i].class == Class::SEPARATOR && expected_token == ExpectedClass::LITERALORSEPARATOR {
76			if tree[i].value.clone().unwrap_or("".to_string()) == "[".to_string() {
77				expected_token = ExpectedClass::LITERAL;
78				i = i + 1;
79				if tree.len() - i == 0 {
80					return Some(format!("Key left undefined on line {}.", line));
81				}
82				continue;
83			} else {
84				return Some(format!("Invalid use of separator syntax on line {}.", line));
85			}
86		}
87
88		if tree[i].class == Class::SEPARATOR && expected_token == ExpectedClass::SEPARATOR {
89			if tree[i].value.clone().unwrap_or("".to_string()) == "]".to_string() {
90				expected_token = ExpectedClass::NEWLINE;
91				i = i + 1;
92				continue;
93			} else if tree[i].value.clone().unwrap_or("".to_string()) == ",".to_string() {
94				expected_token = ExpectedClass::LITERAL;
95				i = i + 1;
96				continue;
97			} else {
98				return Some(format!("Invalid use of separator syntax on line {}.", line));
99			}		
100		}
101
102		if tree[i].value.is_none() {
103			return Some(format!("{:?} found where {:?} expected at line {}.", tree[i].class, expected_token, line));
104		} else {
105			return Some(format!("{:?} {} found where {:?} expected at line {}.", tree[i].class, tree[i].value.clone().unwrap_or("None".to_string()), expected_token, line));
106		}
107	}
108	return None;
109}