139 lines
3 KiB
Rust
139 lines
3 KiB
Rust
// See the end of this file for copyright and license terms.
|
|
|
|
use std::collections::HashMap;
|
|
use std::collections::hash_map::Keys;
|
|
use std::str::Chars;
|
|
|
|
mod lex;
|
|
use crate::lex::{Lexer, SyntaxError};
|
|
|
|
mod parser;
|
|
use parser::Parser;
|
|
|
|
mod ast;
|
|
|
|
pub struct Config {
|
|
nodes: HashMap<String, Node>,
|
|
}
|
|
|
|
impl Config {
|
|
pub fn parse(stream: Chars) -> Result<Config, SyntaxError> {
|
|
let lexer = Lexer::new(stream);
|
|
let parser = Parser::new(lexer);
|
|
let mut nodes = HashMap::new();
|
|
|
|
for nr in parser {
|
|
match nr {
|
|
Ok(node) => {
|
|
let name = node.name.clone();
|
|
nodes.insert(name, node);
|
|
}
|
|
Err(err) => return Err(err),
|
|
}
|
|
}
|
|
|
|
Ok(Config { nodes })
|
|
}
|
|
|
|
pub fn keys(&self) -> Keys<String, Node> {
|
|
self.nodes.keys()
|
|
}
|
|
|
|
pub fn get_node(&self, name: &str) -> Option<&Node> {
|
|
self.nodes.get(name)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Node {
|
|
pub(crate) name: String,
|
|
pub(crate) val: NodeVal,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
enum NodeVal {
|
|
Bool(bool),
|
|
Int(i64),
|
|
String(String),
|
|
}
|
|
|
|
impl Node {
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
pub fn val_bool(&self) -> Option<&bool> {
|
|
match &self.val {
|
|
NodeVal::Bool(b) => Some(b),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn val_int(&self) -> Option<&i64> {
|
|
match &self.val {
|
|
NodeVal::Int(i) => Some(i),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn val_str(&self) -> Option<&String> {
|
|
match &self.val {
|
|
NodeVal::String(s) => Some(s),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait GetNodeVal<T> {
|
|
fn get(&self, name: &str) -> Option<&T>;
|
|
fn get_or<'a>(&'a self, name: &str, default: &'a T) -> &'a T {
|
|
match self.get(name) {
|
|
Some(x) => x,
|
|
None => default,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GetNodeVal<bool> for Config {
|
|
fn get(&self, name: &str) -> Option<&bool> {
|
|
match &self.get_node(name)?.val {
|
|
NodeVal::Bool(b) => Some(b),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GetNodeVal<i64> for Config {
|
|
fn get(&self, name: &str) -> Option<&i64> {
|
|
match &self.get_node(name)?.val {
|
|
NodeVal::Int(i) => Some(i),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GetNodeVal<String> for Config {
|
|
fn get(&self, name: &str) -> Option<&String> {
|
|
match &self.get_node(name)?.val {
|
|
NodeVal::String(s) => Some(s),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait ConfigError {
|
|
fn msg(&self) -> &str;
|
|
fn line(&self) -> usize;
|
|
fn col(&self) -> usize;
|
|
}
|
|
|
|
// Copyright (C) 2021 Fefie <owo@fef.moe>
|
|
// This file is part of gayconf.
|
|
//
|
|
// gayconf is non-violent software: you can use, redistribute,
|
|
// and/or modify it under the terms of the CNPLv6+ as found
|
|
// in the LICENSE file in the source code root directory or
|
|
// at <https://git.pixie.town/thufie/CNPL>.
|
|
//
|
|
// gayconf comes with ABSOLUTELY NO WARRANTY, to the extent
|
|
// permitted by applicable law. See the CNPL for details.
|