use process_line::LineInfo;
use impl_token::AddTokens;
use ::Error;
#[derive(Debug)]
pub struct ParsingLines {
line_counter: u32,
prev_indent_spaces: Vec<usize>,
pub add_tokens: AddTokens,
}
impl ParsingLines {
pub fn new() -> ParsingLines {
ParsingLines {
line_counter: 0,
prev_indent_spaces: Vec::new(),
add_tokens: AddTokens::new(),
}
}
pub fn add_opt_line(&mut self, line: &Option<LineInfo>) -> Result<&ParsingLines, Error> {
self.line_counter += 1;
match *line {
None => Ok(self.add_token()),
Some(ref l) => self.add_line_info(l),
}
}
fn add_line_info(&mut self, l: &LineInfo) -> Result<&ParsingLines, Error> {
match self.prev_indent_spaces.last().cloned() {
None => Ok(self.add_first_line(l)),
Some(last_prev) => {
use std::cmp::Ordering::{Equal, Greater, Less};
match l.indent.cmp(&last_prev) {
Equal => Ok(self.add_line(&l.content)),
Greater => Ok(self.add_subtoken_line(l)),
Less => self.add_backtoken_line(&l),
}
}
}
}
fn add_token(&mut self) -> &Self {
self.add_tokens.add_token();
self
}
fn add_first_line(&mut self, line: &LineInfo) -> &Self {
self.prev_indent_spaces.push(line.indent);
self.add_line(&line.content)
}
fn add_line(&mut self, content: &str) -> &Self {
self.add_tokens
.add_line(content);
self
}
fn add_subtoken_line(&mut self, line: &LineInfo) -> &Self {
self.prev_indent_spaces.push(line.indent);
self.add_tokens
.add_sub_token()
.add_line(&line.content);
self
}
fn add_backtoken_line(&mut self, line: &LineInfo) -> Result<&Self, Error> {
let get_back_level = self.get_back_level_update_prevs(line.indent)?;
self.add_tokens
.add_back_token(get_back_level)
.add_line(&line.content);
Ok(self)
}
fn get_back_level_update_prevs(&mut self, spaces: usize) -> Result<usize, Error> {
fn get_error(line_counter: u32) -> Error {
Error {
line: line_counter,
desc: "invalid indentation".to_owned(),
}
};
use std::cmp::Ordering::{Equal, Greater, Less};
let prev_spaces = self.prev_indent_spaces
.last()
.cloned()
.ok_or(get_error(self.line_counter))?;
match prev_spaces.cmp(&spaces) {
Equal => Ok(self.prev_indent_spaces.len() - 1),
Greater => {
self.prev_indent_spaces.pop();
self.get_back_level_update_prevs(spaces)
}
Less => Err(get_error(self.line_counter)),
}
}
}