frostwalker 0.1.2

A TOML-like configuration language parser with zero dependencies outside of std.
Documentation
//! Module containing the validator which makes sure that a Token list is correct.
use super::{Token, Class};

#[derive(Debug)]
#[derive(PartialEq)]
enum ExpectedClass {
	IDENTIFIER,
	EQUALS,
	NEWLINE,
	LITERALORSEPARATOR,
	LITERAL,
	SEPARATOR,
}

/// Borrows a token list and either outputs None, meaning no error, or Some(String) with an error message inside.
///
/// ```
/// use frostwalker::{validator, Class, Token};
///
/// let ident = Token { class: Class::IDENTIFIER, value: Some("friend".to_string()) };
/// let equals = Token { class: Class::EQUALS, value: None };
/// let val = Token { class: Class::LITERAL, value: Some("ferris".to_string()) };
///
/// assert_eq!(validator::validate(&vec![ident, equals, val]), None);
/// ```
pub fn validate(tree: &Vec<Token>) -> Option<String> {
	let mut expected_token: ExpectedClass = ExpectedClass::IDENTIFIER;
	let mut i = 0;
	let mut line = 1;
	while i < tree.len() {

		if tree[i].class == Class::NEWLINE && i == 0 {
			i = i + 1;
			line = line + 1;
			continue;
		}

		if tree[i].class == Class::NEWLINE && expected_token == ExpectedClass::NEWLINE {
			i = i + 1;
			line = line + 1;
			expected_token = ExpectedClass::IDENTIFIER;
			continue;
		}

		if tree[i].class == Class::IDENTIFIER && expected_token == ExpectedClass::IDENTIFIER {
			i = i + 1;
			if tree.len() - i == 0 {
				return Some(format!("Key left undefined on line {}.", line));
			}
			expected_token = ExpectedClass::EQUALS;
			continue;
		}

		if tree[i].class == Class::EQUALS && expected_token == ExpectedClass::EQUALS {
			i = i + 1;
			expected_token = ExpectedClass::LITERALORSEPARATOR;
			if tree.len() - i == 0 {
				return Some(format!("Key left undefined on line {}.", line));
			}
			continue;
		}

		if (tree[i].class == Class::LITERAL || tree[i].class == Class::BOOLEAN) && expected_token == ExpectedClass::LITERALORSEPARATOR {
			i = i + 1;
			expected_token = ExpectedClass::NEWLINE;
			continue;
		}

		if (tree[i].class == Class::LITERAL || tree[i].class == Class::BOOLEAN) && expected_token == ExpectedClass::LITERAL {
			i = i + 1;
			expected_token = ExpectedClass::SEPARATOR;
			continue;
		}

		if tree[i].class == Class::SEPARATOR && expected_token == ExpectedClass::LITERALORSEPARATOR {
			if tree[i].value.clone().unwrap_or("".to_string()) == "[".to_string() {
				expected_token = ExpectedClass::LITERAL;
				i = i + 1;
				if tree.len() - i == 0 {
					return Some(format!("Key left undefined on line {}.", line));
				}
				continue;
			} else {
				return Some(format!("Invalid use of separator syntax on line {}.", line));
			}
		}

		if tree[i].class == Class::SEPARATOR && expected_token == ExpectedClass::SEPARATOR {
			if tree[i].value.clone().unwrap_or("".to_string()) == "]".to_string() {
				expected_token = ExpectedClass::NEWLINE;
				i = i + 1;
				continue;
			} else if tree[i].value.clone().unwrap_or("".to_string()) == ",".to_string() {
				expected_token = ExpectedClass::LITERAL;
				i = i + 1;
				continue;
			} else {
				return Some(format!("Invalid use of separator syntax on line {}.", line));
			}		
		}

		if tree[i].value.is_none() {
			return Some(format!("{:?} found where {:?} expected at line {}.", tree[i].class, expected_token, line));
		} else {
			return Some(format!("{:?} {} found where {:?} expected at line {}.", tree[i].class, tree[i].value.clone().unwrap_or("None".to_string()), expected_token, line));
		}
	}
	return None;
}