101 lines
No EOL
2 KiB
Rust
101 lines
No EOL
2 KiB
Rust
use std::fmt;
|
|
|
|
use crate::Token;
|
|
|
|
pub enum LispValue {
|
|
Nil,
|
|
String(String),
|
|
LispFunction(String, Vec<OpCode>),
|
|
RustFunction(String, fn(Vec<LispValue>) -> LispValue),
|
|
Exp(OpCode)
|
|
}
|
|
|
|
impl fmt::Display for LispValue {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
LispValue::Nil => write!(f, "nil"),
|
|
LispValue::String(str) => write!(f, "{}", str),
|
|
LispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name),
|
|
LispValue::RustFunction(name, _) => write!(f, "<'{}': Rust Function>", name),
|
|
_ => todo!()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<&str> for LispValue {
|
|
fn from(value: &str) -> Self {
|
|
LispValue::String(value.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<String> for LispValue {
|
|
fn from(value: String) -> Self {
|
|
LispValue::String(value)
|
|
}
|
|
}
|
|
|
|
pub enum OpCode {
|
|
Call(String, Vec<LispValue>),
|
|
Exp(Vec<OpCode>)
|
|
}
|
|
|
|
// TODO: Handle failure
|
|
fn read_exp(open_paren_idx: usize, tokens: &Vec<Token>) -> Option<(Vec<Token>, usize)> /* Option<tokens, close_paren_idx> */ {
|
|
let mut tkns = Vec::new();
|
|
let mut depth = 0;
|
|
|
|
for i in open_paren_idx..tokens.len() - 1 {
|
|
match &tokens[i] {
|
|
Token::OpenParen => {
|
|
if depth != 0 {
|
|
tkns.push(Token::OpenParen);
|
|
}
|
|
depth += 1;
|
|
}
|
|
Token::CloseParen => {
|
|
depth -= 1;
|
|
if depth == 0 {
|
|
return Some((tkns, i));
|
|
}
|
|
}
|
|
token => {
|
|
tkns.push(token.clone());
|
|
}
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn parse_exp(tokens: Vec<Token>) -> Vec<OpCode> {
|
|
todo!()
|
|
}
|
|
|
|
pub fn parse(tokens: Vec<Token>) -> Vec<OpCode> {
|
|
let mut opcodes = Vec::new();
|
|
|
|
let mut current_depth = 0;
|
|
let mut seeking = false;
|
|
|
|
let mut i = 0;
|
|
while i < tokens.len() {
|
|
match &tokens[i] {
|
|
Token::OpenParen => {
|
|
let (tkns, close_paren_idx) = read_exp(i, &tokens).unwrap();
|
|
opcodes.push(OpCode::Exp(parse_exp(tkns)));
|
|
i = close_paren_idx;
|
|
}
|
|
tkn => {
|
|
panic!("Unexpected token {:?}", tkn);
|
|
}
|
|
}
|
|
i += 1;
|
|
}
|
|
|
|
|
|
// opcodes.push(OpCode::Call("print".to_string(), vec![
|
|
// LispValue::from("Hello, World!")
|
|
// ]));
|
|
|
|
opcodes
|
|
} |