add documentation and finish off.
This commit is contained in:
parent
5420ea59ae
commit
878f81b1a4
6 changed files with 80 additions and 2 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4,4 +4,4 @@ version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "frostwalker"
|
name = "frostwalker"
|
||||||
version = "0.0.10"
|
version = "0.1.0"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "frostwalker"
|
name = "frostwalker"
|
||||||
version = "0.0.10"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
|
//! Module containing the formatter which turns the tokens into a HashMap.
|
||||||
use super::{Token, Class};
|
use super::{Token, Class};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// This function creates a HashMap from tokens.
|
||||||
|
///
|
||||||
|
/// It does not do any verification of the source tokens and may panic if something goes wrong.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use frostwalker::{formatter, Token, Class};
|
||||||
|
///
|
||||||
|
/// let identifier = Token { class: Class::IDENTIFIER, value: Some("key".to_string()) };
|
||||||
|
/// let equals = Token { class: Class::EQUALS, value: None };
|
||||||
|
/// let value = Token { class: Class::LITERAL, value: Some("5".to_string()) };
|
||||||
|
///
|
||||||
|
/// let hashmap = formatter::format(vec![identifier, equals, value]);
|
||||||
|
/// assert_eq!(hashmap.get("key").unwrap(), "5");
|
||||||
|
/// ```
|
||||||
pub fn format(tree: Vec<Token>) -> HashMap<String, String> {
|
pub fn format(tree: Vec<Token>) -> HashMap<String, String> {
|
||||||
let mut output = HashMap::new();
|
let mut output = HashMap::new();
|
||||||
let mut current_key = "".to_string();
|
let mut current_key = "".to_string();
|
||||||
|
|
16
src/lexer.rs
16
src/lexer.rs
|
@ -1,9 +1,25 @@
|
||||||
|
//! Module containing the lexer which turns the source into a Token list.
|
||||||
use super::{Token, Class};
|
use super::{Token, Class};
|
||||||
|
|
||||||
|
/// British English spelling for `tokenize()`.
|
||||||
pub fn tokenise(source: &str) -> Vec<Token> {
|
pub fn tokenise(source: &str) -> Vec<Token> {
|
||||||
return tokenize(source);
|
return tokenize(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes in a source string and turns it into a Token list.
|
||||||
|
///
|
||||||
|
/// Any unknown text will be given the class UNKNOWN and will fail when reaching the validator.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use frostwalker::{lexer, Class, Token};
|
||||||
|
///
|
||||||
|
/// let list = lexer::tokenize("meaning_of_life = 42");
|
||||||
|
/// let ident = Token { class: Class::IDENTIFIER, value: Some("meaning_of_life".to_string()) };
|
||||||
|
/// let equals = Token { class: Class::EQUALS, value: None };
|
||||||
|
/// let val = Token { class: Class::LITERAL, value: Some("42".to_string()) };
|
||||||
|
///
|
||||||
|
/// assert_eq!(list, vec![ident, equals, val]);
|
||||||
|
/// ```
|
||||||
pub fn tokenize(source: &str) -> Vec<Token> {
|
pub fn tokenize(source: &str) -> Vec<Token> {
|
||||||
let lines: Vec<&str> = source.lines().collect();
|
let lines: Vec<&str> = source.lines().collect();
|
||||||
let lines_len = lines.len();
|
let lines_len = lines.len();
|
||||||
|
|
35
src/lib.rs
35
src/lib.rs
|
@ -1,5 +1,27 @@
|
||||||
|
//! A TOML-like configuration language parser that supports single depth arrays, integers, strings and boolean literals.
|
||||||
|
//!
|
||||||
|
//! This library isn't intended to compete with `toml`. Frostwalker and `toml` have differing goals and I would recommend you use `toml` over Frostwalker as it supports more features, but Frostwalker has no dependencies apart from the standard library.
|
||||||
|
//!
|
||||||
|
//! The use of this library is easy and doesn't require much work:
|
||||||
|
//! ```
|
||||||
|
//! use frostwalker::parse;
|
||||||
|
//!
|
||||||
|
//! let parsed_output = parse("yes = true\r\nkey = \"value\"\r\narray = [ 1, 5 ]");
|
||||||
|
//! let hashmap = parsed_output.unwrap();
|
||||||
|
//! assert_eq!(hashmap.get("yes").unwrap(), "true");
|
||||||
|
//!
|
||||||
|
//! assert_eq!(hashmap.get("key").unwrap(), "value");
|
||||||
|
//!
|
||||||
|
//! assert_eq!(hashmap.get("array").unwrap(), "2");
|
||||||
|
//! assert_eq!(hashmap.get("array[0]").unwrap(), "1");
|
||||||
|
//! assert_eq!(hashmap.get("array[1]").unwrap(), "5");
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// A structure for a lexical token.
|
||||||
|
///
|
||||||
|
/// It is used by all components of the parser stack and is here as to keep each component separate from the others.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct Token {
|
pub struct Token {
|
||||||
|
@ -7,15 +29,25 @@ pub struct Token {
|
||||||
pub value: Option<String>,
|
pub value: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An enumerator for types of lexical tokens.
|
||||||
|
///
|
||||||
|
/// It is used by all components of the parser stack and is here as to keep each component separate from the others.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum Class {
|
pub enum Class {
|
||||||
|
/// Names and keys assigned by the programmer.
|
||||||
IDENTIFIER,
|
IDENTIFIER,
|
||||||
|
/// Punctuation and delimiters.
|
||||||
SEPARATOR,
|
SEPARATOR,
|
||||||
|
/// Equals.
|
||||||
EQUALS,
|
EQUALS,
|
||||||
|
/// Strings and integers.
|
||||||
LITERAL,
|
LITERAL,
|
||||||
|
/// New lines.
|
||||||
NEWLINE,
|
NEWLINE,
|
||||||
|
/// True and false.
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
|
/// Tokens that do not fit the lexer's ruleset.
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +55,9 @@ pub mod lexer;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
pub mod formatter;
|
pub mod formatter;
|
||||||
|
|
||||||
|
/// The parsing function. This function takes in a string with configuration in it and either outputs a HashMap containing keys and values or an error message.
|
||||||
|
///
|
||||||
|
/// The parser wraps around each function of the parser stack (lexer, validator, and formatter) as to ensure the configuration text is parsed properly. Errors originate from the validator.
|
||||||
pub fn parse(source: &str) -> Result<HashMap<String, String>, String> {
|
pub fn parse(source: &str) -> Result<HashMap<String, String>, String> {
|
||||||
let tree = lexer::tokenize(source);
|
let tree = lexer::tokenize(source);
|
||||||
let result = validator::validate(&tree);
|
let result = validator::validate(&tree);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Module containing the validator which makes sure that a Token list is correct.
|
||||||
use super::{Token, Class};
|
use super::{Token, Class};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -11,6 +12,17 @@ enum ExpectedClass {
|
||||||
SEPARATOR,
|
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> {
|
pub fn validate(tree: &Vec<Token>) -> Option<String> {
|
||||||
let mut expected_token: ExpectedClass = ExpectedClass::IDENTIFIER;
|
let mut expected_token: ExpectedClass = ExpectedClass::IDENTIFIER;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
Loading…
Reference in a new issue