1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00
bobbylisp/src/parser.rs

92 lines
2.8 KiB
Rust
Raw Normal View History

2022-01-21 17:43:50 -06:00
use regex::Regex;
use std::rc::Rc;
use crate::{
2022-01-22 15:36:13 -06:00
lexer::{Token, here},
2022-01-21 17:43:50 -06:00
token::{Expr::{self, Null, List, Vector}, Return, Error::{self, ErrorString}}, list, vector,
};
const INT_REGEX: &str = r#"^-?[0-9]+$"#;
const STRING_REGEX: &str = r#""(?:\\.|[^\\"])*""#;
struct Reader {
2022-01-22 15:36:13 -06:00
src: String,
2022-01-21 17:43:50 -06:00
tokens: Vec<Token>,
position: usize,
}
impl Reader {
2022-01-22 15:36:13 -06:00
fn new(tokens: Vec<Token>, src: String) -> Reader {
2022-01-21 17:43:50 -06:00
Reader {
2022-01-22 15:36:13 -06:00
src,
2022-01-21 17:43:50 -06:00
tokens,
position: 0,
}
}
fn next(&mut self) -> Result<&Token, Error> {
self.position += 1;
Ok(self.tokens.get(self.position - 1).ok_or(ErrorString("Underflow".to_string()))?)
}
fn peek(&mut self) -> Result<&Token, Error> {
Ok(self.tokens.get(self.position).ok_or(ErrorString("Underflow".to_string()))?)
}
}
fn read_atom(reader: &mut Reader) -> Return {
let int_regex = Regex::new(INT_REGEX).unwrap();
let string_regex = Regex::new(STRING_REGEX).unwrap();
let token = reader.next()?;
match &token.value[..] {
"null" => Ok(Expr::Null),
"true" => Ok(Expr::Bool(true)),
"false" => Ok(Expr::Bool(false)),
_ => {
if int_regex.is_match(&token.value) {
Ok(Expr::Number(token.value.parse().unwrap()))
} else if string_regex.is_match(&token.value) {
Ok(Expr::String(token.value[1..token.value.len() - 1].to_string()))
} else {
Ok(Expr::Symbol(token.value.to_string()))
}
}
}
}
fn read_sequence(reader: &mut Reader, end: &str) -> Return {
let mut sequence: Vec<Expr> = Vec::new();
2022-01-22 15:36:13 -06:00
let _current_token_ = reader.next()?;
2022-01-21 17:43:50 -06:00
loop {
let token = match reader.peek() {
Ok(token) => token,
2022-01-22 15:36:13 -06:00
Err(_) => return Err(ErrorString(
format!("{} Unexpected end of input, expected '{}'", here(&reader.src, &reader.tokens[reader.position - 1]), end)
)),
2022-01-21 17:43:50 -06:00
};
if token.value == end { break; }
sequence.push(read_form(reader)?)
}
2022-01-22 15:36:13 -06:00
let _match_token_ = reader.next()?;
2022-01-21 17:43:50 -06:00
match end {
")" => Ok(list!(sequence)),
"]" => Ok(vector!(sequence)),
_ => return Err(ErrorString(format!("Unknown sequence end value: '{}'", end))),
}
}
fn read_form(reader: &mut Reader) -> Return {
let token = reader.peek()?;
match &token.value[..] {
")" => Err(ErrorString("Unexpected ')'".to_string())),
2022-01-22 15:36:13 -06:00
"(" => read_sequence(reader, ")"),
2022-01-21 17:43:50 -06:00
"]" => Err(ErrorString("Unexpected ']'".to_string())),
2022-01-22 15:36:13 -06:00
"[" => read_sequence(reader, "]"),
2022-01-21 17:43:50 -06:00
_ => read_atom(reader),
}
}
2022-01-22 15:36:13 -06:00
pub fn parse(tokens: Vec<Token>, src: &str) -> Return {
2022-01-21 17:43:50 -06:00
if tokens.len() == 0 { return Ok(Null); }
2022-01-22 15:36:13 -06:00
read_form(&mut Reader::new(tokens, src.to_string()))
2022-01-21 17:43:50 -06:00
}