You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.8 KiB
Rust
113 lines
2.8 KiB
Rust
4 years ago
|
use crate::graph::{Graph, Node};
|
||
|
use std::collections::HashMap;
|
||
|
use std::fmt::Error;
|
||
|
|
||
|
enum State {
|
||
|
Default,
|
||
|
Edge,
|
||
|
Node(String),
|
||
|
AnonymousNode,
|
||
|
}
|
||
|
|
||
|
struct Consumer {
|
||
|
lines: Vec<String>,
|
||
|
state: ConsumerState,
|
||
|
}
|
||
|
|
||
|
struct ConsumerState {
|
||
|
line: usize,
|
||
|
position: usize,
|
||
|
absolute_position: u64,
|
||
|
}
|
||
|
|
||
|
impl Consumer {
|
||
|
fn consume_from_line(&mut self) -> Option<char> {
|
||
|
if let Some(chxr) = self.peek_on_line() {
|
||
|
self.push_char();
|
||
|
Some(chxr)
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn peek_on_line(&mut self) -> Option<char> {
|
||
|
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<Graph, ParserError> {
|
||
|
let mut nodes: Vec<Node>;
|
||
|
let mut node_names: HashMap<String, u32>;
|
||
|
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())
|
||
|
}
|