Reid/src/parser/mod.rs

328 lines
8.9 KiB
Rust

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<char>,
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<ParsedReid, SyntaxError> {
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<char> {
if self.remaining() < (index + 1) {
None
} else {
Some(self.text[self.cursor + index])
}
}
pub fn expect<T: Into<String>>(&mut self, expectable: Expectable<T>) -> 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<T: Into<String>>(&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<String> = 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<String> = 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<String> = 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<T: Into<String>> {
Static(T),
Ident,
StringLit,
}
pub struct Expect<'a> {
text: Option<String>,
parser: &'a mut Parser,
}
impl<'a> Expect<'a> {
pub fn get_inconfident(self) -> Option<String> {
self.text
}
pub fn get(self) -> Option<String> {
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<String, SyntaxError> {
match self.get() {
Some(text) => Ok(text),
None => Err(error),
}
}
pub fn and<'b, T: Into<String>>(self, other: Expectable<T>) -> 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<Vec<String>>,
parser: &'a mut Parser,
}
impl<'a> Expects<'a> {
pub fn and<'b, T: Into<String>>(mut self, expect: Expectable<T>) -> 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<Vec<String>> {
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)
}
}