use crate::graph::{Graph, Node}; use std::collections::HashMap; use std::fmt::Error; enum State { Default, Edge, Node(String), AnonymousNode, } struct Consumer { lines: Vec, state: ConsumerState, } struct ConsumerState { line: usize, position: usize, absolute_position: u64, } impl Consumer { fn consume_from_line(&mut self) -> Option { if let Some(chxr) = self.peek_on_line() { self.push_char(); Some(chxr) } else { None } } fn peek_on_line(&mut self) -> Option { let line = &self.lines[self.state.line]; if self.state.position + 1 >= line.len() { None } else { Ok(line[self.state.position + 1]) } } fn push_char(&mut self) { self.state.position += 1; self.state.absolute_position += 1; } fn new(content: String) -> Consumer { Consumer { lines: content .lines() .map(|x| String::from(x)) .collect(), state: ConsumerState { position: 0, line: 0, absolute_position: 0, }, } } } pub struct ParserError { message: String, absolute_position: u64, position: usize, line: usize, } impl ParserError { fn from_consumer(consumer: &Consumer, error: &str) -> ParserError { ParserError { message: error.to_string(), absolute_position: consumer.state.absolute_position, position: consumer.state.position, line: consumer.state.line } } } pub fn parse(contents: String) -> Result { let mut nodes: Vec; let mut node_names: HashMap; let mut state = State::Default; let mut consumer = Consumer::new(contents); while consumer.consume_line() { while let Some(chxr) = consumer.consume_from_line() { match state { State::Default => { match chxr { '\\' => { if consumer.peek_on_line() == Some('(') { consumer.consume_from_line(); state = State::AnonymousNode; } else { return Err(ParserError::from_consumer(&consumer, "Found \\ without valid next character")); } } 'a'..'z' | 'A'..'Z' => { state = State::Node(chxr.to_string()) } } } _ => {} } } } println!("{:?}", lines); Ok(Graph::default()) }