mod parsed_reid; use super::errors::CompilerError; use parsed_reid::{Expression, ParsedReid, Statement}; use std::fmt; use std::fmt::Display; const ALLOWED_IDENT_CHARS: [char; 38] = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '-', ]; const ALLOWED_IDENT_BEGIN_CHARS: [char; 26] = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ]; pub struct Parser { text: Vec, cursor: usize, line_number: usize, character_number: usize, } impl Parser { pub fn from(text: String) -> Self { Parser { text: text.chars().collect(), cursor: 0, line_number: 0, character_number: 0, } } pub fn parse(mut self) -> Result { let mut statement_list = Vec::new(); let mut error = None; while { self.skip_whitespace(); if self.remaining() > 0 { match Statement::parse(&mut self) { Ok(exp) => { statement_list.push(exp); true } Err(err) => { error = Some(err); false } } } else { false } } {} if let Some(error) = error { Err(error) } else { Ok(ParsedReid(Expression::BlockExpr( Position(0, 0), statement_list, ))) } } pub fn remaining(&self) -> usize { self.text.len() - self.cursor } pub fn peek(&mut self, index: usize) -> Option { if self.remaining() < (index + 1) { None } else { Some(self.text[self.cursor + index]) } } pub fn expect>(&mut self, expected: T) -> Expect { let expected = expected.into(); self.skip_whitespace(); let mut result = Some(expected.clone()); for (idx, c) in expected.chars().enumerate() { if let Some(peek) = self.peek(idx) { if peek != c { result = None; } } else { result = None; break; } } Expect { text: result, len: expected.len(), parser: self, } } pub fn expect_ident(&mut self) -> Expect { self.skip_whitespace(); let mut ident: Option = None; let mut len = 0; while { if let Some(peek) = self.peek(len) { let lowercase = &peek.to_ascii_lowercase(); if let Some(id) = &mut ident { if ALLOWED_IDENT_CHARS.contains(lowercase) { id.push(peek); len += 1; true } else { false } } else { if ALLOWED_IDENT_BEGIN_CHARS.contains(lowercase) { ident = Some(peek.to_string()); len += 1; true } else { false } } } else { false } } {} Expect { text: ident, len: len, parser: self, } } pub fn expect_string_lit(&mut self) -> Expect { self.skip_whitespace(); let mut content: Option = None; let mut len = 0; while { if let Some(peek) = self.peek(len) { if let Some(cont) = &mut content { if peek == '"' { len += 1; false } else { cont.push(peek); len += 1; true } } else { if peek == '"' { content = Some(String::new()); len += 1; true } else { false } } } else { false } } {} Expect { text: content, len: len, parser: self, } } pub fn move_cursor(&mut self) { let curr = self.peek(0).unwrap(); self.cursor += 1; self.character_number += 1; if curr == '\n' { self.character_number = 0; self.line_number += 1; } } pub fn move_cursor_multiple(&mut self, amount: usize) { for _ in 0..amount { self.move_cursor(); } } pub fn pos(&self) -> Position { Position(self.line_number, self.character_number) } fn skip_whitespace(&mut self) { let mut next = ' '; while self.remaining() > 0 && { next = self.peek(0).unwrap(); next == ' ' || next == '\n' || next == '\r' || next == '\t' } { self.move_cursor(); } } } pub struct Expect<'a> { text: Option, len: usize, parser: &'a mut Parser, } impl Expect<'_> { pub fn get(self) -> Option { if self.text.is_some() { self.parser.move_cursor_multiple(self.len); } self.text } pub fn get_or(self, error: CompilerError) -> Result { match self.get() { Some(text) => Ok(text), None => Err(error), } } } #[derive(Debug, Copy, Clone)] pub struct Position(usize, usize); impl Display for Position { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "line {}, column {}", self.0, self.1) } }