mod parsed_reid; use super::errors::SyntaxError; pub use parsed_reid::*; 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', ]; const ALLOWED_NUMERALS: [char; 10] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; pub struct Parser { text: Vec, cursor: usize, inconfidence: usize, line_number: usize, character_number: usize, } impl Parser { pub fn from(text: String) -> Self { Parser { text: text.chars().collect(), cursor: 0, inconfidence: 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_confident(true); 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, expectable: Expectable) -> Expect { match expectable { Expectable::Static(val) => self.expect_static(val), Expectable::Ident => self.expect_ident(), Expectable::StringLit => self.expect_string_lit(), } } pub fn expect_static>(&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 + self.inconfidence) { if peek != c { result = None; } } else { result = None; break; } } self.inconfidence += expected.len(); Expect { text: result, parser: self, } } pub fn expect_ident(&mut self) -> Expect { self.skip_whitespace(); let mut ident: Option = None; while { if let Some(peek) = self.peek(self.inconfidence) { let lowercase = &peek.to_ascii_lowercase(); if let Some(id) = &mut ident { if ALLOWED_IDENT_CHARS.contains(lowercase) { id.push(peek); self.inconfidence += 1; true } else { false } } else { if ALLOWED_IDENT_BEGIN_CHARS.contains(lowercase) { ident = Some(peek.to_string()); self.inconfidence += 1; true } else { false } } } else { false } } {} Expect { text: ident, parser: self, } } pub fn expect_string_lit(&mut self) -> Expect { self.skip_whitespace(); let mut content: Option = None; while { if let Some(peek) = self.peek(self.inconfidence) { if let Some(cont) = &mut content { if peek == '"' { self.inconfidence += 1; false } else { cont.push(peek); self.inconfidence += 1; true } } else { if peek == '"' { content = Some(String::new()); self.inconfidence += 1; true } else { false } } } else { false } } {} Expect { text: content, parser: self, } } pub fn expect_numeral_lit(&mut self) -> Expect { self.skip_whitespace(); let mut content: Option = None; while { if let Some(peek) = self.peek(self.inconfidence) { if ALLOWED_NUMERALS.contains(&peek) { let mut string = match content { Some(s) => s, None => String::new(), }; string.push(peek); content = Some(string); self.inconfidence += 1; true } else { false } } else { false } } {} Expect { text: content, parser: self, } } pub fn advance_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 advance_cursor_multiple(&mut self, amount: usize) { for _ in 0..amount { self.advance_cursor(); } } pub fn pos(&self) -> Position { Position(self.line_number, self.character_number) } #[allow(unused_assignments)] fn skip_whitespace_confident(&mut self, confident: bool) { let mut next = ' '; while self.remaining() > 0 && { next = self.peek(self.inconfidence).unwrap(); next == ' ' || next == '\n' || next == '\r' || next == '\t' } { if confident { self.advance_cursor(); } else { self.inconfidence += 1; } } } fn skip_whitespace(&mut self) { self.skip_whitespace_confident(false); } } #[allow(dead_code)] pub enum Expectable> { Static(T), Ident, StringLit, } pub struct Expect<'a> { text: Option, parser: &'a mut Parser, } impl<'a> Expect<'a> { pub fn get_inconfident(self) -> Option { self.text } pub fn get(self) -> Option { if self.text.is_some() { self.parser .advance_cursor_multiple(self.parser.inconfidence); } self.parser.inconfidence = 0; self.text } pub fn get_or(self, error: SyntaxError) -> Result { match self.get() { Some(text) => Ok(text), None => Err(error), } } pub fn and<'b, T: Into>(self, other: Expectable) -> Expects<'a> { let texts = if let Some(text) = self.text { Some(vec![text]) } else { None }; Expects::and( Expects { texts: texts, parser: self.parser, }, other, ) } } pub struct Expects<'a> { texts: Option>, parser: &'a mut Parser, } impl<'a> Expects<'a> { pub fn and<'b, T: Into>(mut self, expect: Expectable) -> Expects<'a> { let other = self.parser.expect(expect); if let Some(texts) = &mut self.texts { if let Some(text) = other.get_inconfident() { texts.push(text); } else { self.texts = None; } } self } pub fn get(self) -> Option> { if self.texts.is_some() { self.parser .advance_cursor_multiple(self.parser.inconfidence); } self.parser.inconfidence = 0; self.texts } } #[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) } }