use std::fs;
use std::io;
use std::io::prelude::*;
use nom::{IResult};
#[derive(Debug)]
pub enum Error {
Io(io::Error),
Lex(String, usize, String),
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error::Io(e)
}
}
#[derive(Debug)]
pub enum Token {
Header(String),
Pair(String, String),
Single(String),
}
named!(parse_header<&str, &str>, do_parse!(
tag!("[") >>
inner: take_until!("]") >>
tag!("]") >>
(inner.trim())
));
named!(parse_key<&str, &str>, do_parse!(
key: take_until!("=") >>
tag!("=") >>
(key.trim())
));
pub fn lex_ini(filename: &str) -> Result<Vec<Token>, Error> {
let mut tok_list = Vec::new();
let config_file = fs::File::open(filename)?;
let config_reader = io::BufReader::new(config_file);
for line in config_reader.lines() {
let line = line?;
let line = line.trim();
if line.is_empty() || line.starts_with("#") {
} else if let IResult::Done(_, name) = parse_header(&line) {
tok_list.push(Token::Header(name.into()))
} else if let IResult::Done(value, key) = parse_key(&line) {
let value = value.trim();
if key == "Include" {
tok_list.append(&mut lex_ini(value)?);
} else {
tok_list.push(Token::Pair(key.into(), value.into()));
}
} else {
tok_list.push(Token::Single(line.into()));
}
}
Ok(tok_list)
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
}
}