mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
refactor: simplify list
This commit is contained in:
parent
1859a9c4bb
commit
7040bbaa12
0
src/compile/mod.rs
Normal file
0
src/compile/mod.rs
Normal file
16
src/main.rs
16
src/main.rs
|
@ -1,6 +1,7 @@
|
|||
use std::{process::exit, fs::read_to_string};
|
||||
|
||||
pub mod parser;
|
||||
pub mod compile;
|
||||
|
||||
const EXECUTABLE_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const HELP_MESSAGE: &str = "\
|
||||
|
@ -35,10 +36,19 @@ fn main() {
|
|||
if args_index < args.len() {
|
||||
let file_path: &str = &args[args_index];
|
||||
let file_content: String = read_to_string(file_path).unwrap();
|
||||
let ast = parser::parse(&file_content);
|
||||
for node in ast {
|
||||
println!("{:?}", node);
|
||||
|
||||
let parsed = parser::parse(&file_content);
|
||||
let mut ast = Vec::new();
|
||||
for node in parsed {
|
||||
match node {
|
||||
Ok(node) => { ast.push(node); },
|
||||
Err(error) => {
|
||||
eprintln!("ERROR: {}", error);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{:#?}", ast);
|
||||
} else {
|
||||
println!("No file provided.");
|
||||
display_help(1);
|
||||
|
|
100
src/parser.rs
100
src/parser.rs
|
@ -2,25 +2,7 @@
|
|||
// brundonsmith/rust_lisp (https://github.com/brundonsmith/rust_lisp)
|
||||
// go check them out!
|
||||
|
||||
use std::{ rc::Rc, cell::RefCell };
|
||||
|
||||
/// A List in Sexpr
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct List {
|
||||
pub value: Option<Rc<RefCell<Cons>>>,
|
||||
}
|
||||
|
||||
impl List {
|
||||
pub const NIL: List = List { value: None };
|
||||
}
|
||||
|
||||
/// Cons -> (car, [cdr])
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Cons {
|
||||
pub car: Value,
|
||||
pub cdr: Option<Rc<RefCell<Cons>>>,
|
||||
}
|
||||
|
||||
use std::{ rc::Rc, fmt };
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Value {
|
||||
|
@ -30,11 +12,9 @@ pub enum Value {
|
|||
Int(i64), Float(f64),
|
||||
|
||||
String(String), Symbol(String),
|
||||
List(List),
|
||||
}
|
||||
List(Rc<Value>, Rc<Vec<Value>>),
|
||||
|
||||
impl Value {
|
||||
pub const NIL: Value = Value::List(List::NIL);
|
||||
Nil,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -48,36 +28,25 @@ impl Tree {
|
|||
match self {
|
||||
Tree::Atom { atom, quote } => {
|
||||
if quote {
|
||||
Value::List(List {
|
||||
value: Some(Rc::new(RefCell::new(Cons {
|
||||
car: Value::Symbol(String::from("quote")),
|
||||
cdr: Some(Rc::new(RefCell::new(Cons {
|
||||
car: atom, // car vroom vroom 🚗
|
||||
cdr: None,
|
||||
}))),
|
||||
}))),
|
||||
})
|
||||
Value::List(
|
||||
Rc::new(Value::Symbol(String::from("quote"))),
|
||||
Rc::new(vec![atom])
|
||||
)
|
||||
} else {
|
||||
atom
|
||||
}
|
||||
},
|
||||
Tree::List { vec, quote } => {
|
||||
let list = Value::List(
|
||||
vec.into_iter()
|
||||
.map(|tree| tree.into_expr())
|
||||
.collect::<List>(),
|
||||
Rc::new(vec[0].clone().into_expr()),
|
||||
Rc::new(vec[1..].iter().map(|a| a.clone().into_expr()).collect())
|
||||
);
|
||||
|
||||
if quote {
|
||||
Value::List(List {
|
||||
value: Some(Rc::new(RefCell::new(Cons {
|
||||
car: Value::Symbol(String::from("quote")),
|
||||
cdr: Some(Rc::new(RefCell::new(Cons {
|
||||
car: list, // car vroom vroom 🚗
|
||||
cdr: None,
|
||||
}))),
|
||||
}))),
|
||||
})
|
||||
Value::List(
|
||||
Rc::new(Value::Symbol(String::from("quote"))),
|
||||
Rc::new(vec![list])
|
||||
)
|
||||
} else {
|
||||
list
|
||||
}
|
||||
|
@ -86,30 +55,6 @@ impl Tree {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Value> for List {
|
||||
fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
|
||||
let mut list = List { value: None };
|
||||
let mut tail: Option<Rc<RefCell<Cons>>> = None;
|
||||
|
||||
for value in iter {
|
||||
let new_cons = Rc::new(RefCell::new(Cons {
|
||||
car: value,
|
||||
cdr: None,
|
||||
}));
|
||||
|
||||
if list.value.is_none() {
|
||||
list.value = Some(new_cons.clone());
|
||||
} else if let Some(ref tail_cons) = tail {
|
||||
tail_cons.as_ref().borrow_mut().cdr = Some(new_cons.clone());
|
||||
}
|
||||
|
||||
tail = Some(new_cons);
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
// --- Start tokenizer ---
|
||||
|
||||
const SPECIAL_CHARS: [&str; 4] = ["(", ")", "'", "..."];
|
||||
|
@ -205,16 +150,29 @@ pub fn tokenize(src: &str) -> impl Iterator<Item = (&str, (usize, usize))> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseErrorKind {
|
||||
UnexpectedParenOpen,
|
||||
UnexpectedParenClose,
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseErrorKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ParseErrorKind::UnexpectedParenClose => write!(f, "Unexpected ')'"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseError {
|
||||
pub kind: ParseErrorKind,
|
||||
pub pos: (usize, usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} at {}", self.kind, self.pos.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseError {
|
||||
fn new(kind: ParseErrorKind, pos: (usize, usize)) -> Self {
|
||||
ParseError { kind, pos }
|
||||
|
@ -266,7 +224,7 @@ fn read<'a>(
|
|||
if let Tree::List { vec, quote } = &finished {
|
||||
if vec.is_empty() {
|
||||
finished = Tree::Atom {
|
||||
atom: Value::NIL,
|
||||
atom: Value::Nil,
|
||||
quote: *quote,
|
||||
};
|
||||
}
|
||||
|
@ -305,7 +263,7 @@ fn read_atom(token: &str) -> Value {
|
|||
match lower.as_str() {
|
||||
"true" => Value::True,
|
||||
"false" => Value::False,
|
||||
"nil" => Value::NIL,
|
||||
"nil" => Value::Nil,
|
||||
_ => {
|
||||
// Parse number
|
||||
if let Ok(int) = token.parse::<i64>() { Value::Int(int) }
|
||||
|
|
Loading…
Reference in a new issue