use super::errors::CompilerError; use std::fmt; use std::fmt::Display; type Ident = String; 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 exp_list = Vec::new(); let mut error = None; while { self.skip_whitespace(); if self.remaining() > 0 { match Expression::parse(&mut self) { Ok(exp) => { exp_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), exp_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(); } } fn empty() -> Parser { Parser { text: Vec::new(), cursor: 0, character_number: 0, line_number: 0, } } } #[derive(Debug)] pub struct ParsedReid(Expression); #[derive(Debug)] pub enum Expression { BlockExpr(Position, Vec), StatementExpr(Position, Statement), EmptyExpr, } impl Expression { pub fn parse(parser: &mut Parser) -> Result { let begin_pos = parser.pos(); let expect = parser.expect("{"); if let Some(_) = expect.get() { let mut exp_list = Vec::new(); while { match Expression::parse(parser) { Ok(exp) => { exp_list.push(exp); true } Err(_) => false, } } {} if let Some(_) = parser.expect("}").get() { Ok(Expression::BlockExpr(begin_pos, exp_list)) } else { Err(CompilerError::ExpectedToken(parser.pos(), '}')) } } else { match Statement::parse(parser) { Ok(statement) => Ok(Expression::StatementExpr(begin_pos, statement)), Err(err) => Err(CompilerError::ExpectedExpression(begin_pos, Box::new(err))), } } } } #[derive(Debug)] pub enum Statement { LetStatement(Position, Ident, Box), ValueRef(Position, Pattern), } impl Statement { pub fn parse(parser: &mut Parser) -> Result { let pos = parser.pos(); if let Some(_) = parser.expect("let").get() { let ident = parser .expect_ident() .get_or(CompilerError::ExpectedIdent(pos))?; parser .expect("=") .get_or(CompilerError::ExpectedToken(pos, '='))?; match Expression::parse(parser) { Ok(expr) => { parser .expect(";") .get_or(CompilerError::ExpectedToken(pos, ';'))?; Ok(Statement::LetStatement(pos, ident, Box::new(expr))) } Err(err) => Err(CompilerError::ExpectedExpression(pos, Box::new(err))), } } else if let Ok(pattern) = Pattern::parse(parser) { Ok(Statement::ValueRef(pos, pattern)) } else { Err(CompilerError::ExpectedStatement(pos)) } } } #[derive(Debug)] pub enum Pattern { IdentPattern(Position, Ident), LiteralPattern(Position, LiteralPattern), } impl Pattern { fn parse(parser: &mut Parser) -> Result { let pos = parser.pos(); if let Some(string) = parser.expect_string_lit().get() { Ok(Pattern::LiteralPattern( pos, LiteralPattern::StringLit(string), )) } else if let Some(ident) = parser.expect_ident().get() { Ok(Pattern::IdentPattern(pos, ident)) } else { Err(CompilerError::ExpectedPattern(pos)) } } } #[derive(Debug)] pub enum LiteralPattern { StringLit(String), } pub struct Expect<'a> { text: Option, len: usize, parser: &'a mut Parser, } impl Expect<'_> { pub fn get(mut self) -> Option { if self.text.is_some() { self.parser.move_cursor_multiple(self.len); } self.text } pub fn get_or(mut 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) } }