use crate::common::position::CaretPos;
use crate::parse::lex::token::Lex;
use crate::parse::lex::token::Token;
#[derive(Clone, Debug)]
pub struct State {
newlines: Vec<Lex>,
cur_indent: i32,
line_indent: i32,
token_this_line: bool,
pub pos: CaretPos,
}
impl State {
pub fn new() -> State {
let pos = CaretPos::new(1, 1);
State { newlines: vec![], cur_indent: 1, line_indent: 1, token_this_line: false, pos }
}
pub fn flush_indents(&mut self) -> Vec<Lex> {
let amount = ((self.cur_indent) / 4) as usize;
self.cur_indent = 1;
vec![Lex::new(self.pos, Token::Dedent); amount]
}
pub fn token(&mut self, token: Token) -> Vec<Lex> {
if token == Token::NL {
self.newline();
return vec![];
}
self.token_this_line = true;
let mut res = self.newlines.pop().map_or(vec![], |nl| vec![nl]);
if self.line_indent >= self.cur_indent {
let amount = ((self.line_indent - self.cur_indent) / 4) as usize;
res.append(&mut vec![Lex::new(self.pos, Token::Indent); amount]);
} else {
let amount = ((self.cur_indent - self.line_indent) / 4) as usize;
res.append(&mut vec![Lex::new(self.pos, Token::Dedent); amount]);
res.push(Lex::new(self.pos, Token::NL));
}
res.append(&mut self.newlines);
res.push(Lex::new(self.pos, token.clone()));
self.cur_indent = self.line_indent;
self.pos = self.pos.offset_pos(token.clone().width());
if let Token::Str(_str, _) = &token {
self.pos = self.pos.offset_line((_str.lines().count() as i32 - 1) as usize);
} else if let Token::DocStr(_str) = &token {
self.pos = self.pos.offset_line((_str.lines().count() as i32 - 1) as usize);
}
res
}
fn newline(&mut self) {
self.newlines.push(Lex::new(self.pos, Token::NL));
self.token_this_line = false;
self.line_indent = 1;
self.pos = self.pos.newline();
}
pub fn space(&mut self) {
self.pos = self.pos.offset_pos(1);
self.line_indent += i32::from(!self.token_this_line);
}
}