Did stuff
This commit is contained in:
parent
dd23759f85
commit
2def36a617
13 changed files with 220 additions and 23 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -118,6 +118,7 @@ dependencies = [
|
|||
"clap",
|
||||
"hence",
|
||||
"itertools",
|
||||
"num-parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
;; test module
|
||||
(module test
|
||||
"Main module"
|
||||
(defun main ()
|
||||
"Program entrypoint"
|
||||
(let ((x (+ 40 2))))
|
||||
(debug x)))
|
||||
;; main function
|
||||
(defun main ()
|
||||
"Program entrypoint"
|
||||
(let ((x (+ 40 2))))
|
||||
(debug x))
|
||||
|
|
|
@ -32,7 +32,7 @@ impl assembler::ToCode for Arg {
|
|||
}
|
||||
}
|
||||
|
||||
impl assembler::ByteResolvable for Arg {
|
||||
impl assembler::ByteResolvable<assembler::Data> for Arg {
|
||||
fn resolve_number(&self, data: &mut assembler::Data) -> Result<u16, String> {
|
||||
match self {
|
||||
Arg::String(x) => {
|
||||
|
|
|
@ -9,10 +9,10 @@ pub trait ToCode {
|
|||
fn to_code(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait ByteResolvable {
|
||||
fn resolve_number(&self, data: &mut Data) -> Result<u16, String>;
|
||||
pub trait ByteResolvable<T> {
|
||||
fn resolve_number(&self, data: &mut T) -> Result<u16, String>;
|
||||
|
||||
fn resolve_bytes(&self, data: &mut Data) -> Result<Vec<u8>, String>;
|
||||
fn resolve_bytes(&self, data: &mut T) -> Result<Vec<u8>, String>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -9,7 +9,7 @@ pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST, &'static str> {
|
|||
let mut iter = tokens.iter().peekable();
|
||||
let mut body: Vec<ast::Node> = Vec::new();
|
||||
|
||||
while let Some(token) = iter.peek() {
|
||||
while let Some(&token) = iter.peek() {
|
||||
match token {
|
||||
lexer::Token::Comment(x) => {
|
||||
body.push(ast::Node::Comment(x.trim().to_string()));
|
||||
|
@ -60,7 +60,7 @@ pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST, &'static str> {
|
|||
lexer::Token::Whitespace(_) | lexer::Token::Newline(_) => {
|
||||
iter.next();
|
||||
}
|
||||
_ => return Err("Unexspected token"),
|
||||
_ => return Err("Unexpected token"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,3 +16,4 @@ path = "src/bin/main.rs"
|
|||
hence = { path = "../hence" }
|
||||
clap = { version = "3.2.12", features = ["derive"] }
|
||||
itertools = "0.10.3"
|
||||
num-parse = "0.1.2"
|
||||
|
|
|
@ -16,6 +16,20 @@ enum Commands {
|
|||
#[clap(value_parser)]
|
||||
src: String,
|
||||
},
|
||||
#[clap(about = "Parses source code and outputs AST")]
|
||||
Parse {
|
||||
#[clap(value_parser)]
|
||||
src: String,
|
||||
},
|
||||
#[clap(about = "Compiles source code to hence assembly")]
|
||||
Compile {
|
||||
#[clap(value_parser)]
|
||||
src: String,
|
||||
#[clap(value_parser)]
|
||||
out: Option<String>,
|
||||
#[clap(long, action)]
|
||||
dump: bool,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -26,5 +40,20 @@ fn main() {
|
|||
let tokens = lexer::lex(source).unwrap();
|
||||
dbg!(tokens);
|
||||
}
|
||||
Commands::Parse { src } => {
|
||||
let source = fs::read_to_string(src).unwrap();
|
||||
let tokens = lexer::lex(source).unwrap();
|
||||
let ast = parser::parse(tokens).unwrap();
|
||||
dbg!(ast);
|
||||
}
|
||||
Commands::Compile { src, out, dump } => {
|
||||
let source = fs::read_to_string(src).unwrap();
|
||||
let tokens = lexer::lex(source).unwrap();
|
||||
let ast = parser::parse(tokens).unwrap();
|
||||
|
||||
let mut data = compiler::Data::new();
|
||||
compiler::compile(ast, &mut data).unwrap();
|
||||
dbg!(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
61
hencelisp/src/lib/compiler.rs
Normal file
61
hencelisp/src/lib/compiler.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use hence;
|
||||
|
||||
use crate::parser;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
pub struct Data {
|
||||
pub body: Vec<hence::parser::ast::Node>,
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
body: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn create_call(list: Vec<parser::ast::Node>) -> Result<Call, &'static str> {
|
||||
// let mut raw_content = list.iter();
|
||||
// let content = raw_content.by_ref();
|
||||
|
||||
// let name = match content
|
||||
// .skip_while(|n| matches!(n, parser::ast::Node::Comment(_)))
|
||||
// .next()
|
||||
// {
|
||||
// Some(node) => match node {
|
||||
// parser::ast::Node::String(x)
|
||||
// | parser::ast::Node::Symbol(x)
|
||||
// | parser::ast::Node::Literal(x) => x.clone(),
|
||||
// _ => return Err("Invalid call name node literal"),
|
||||
// },
|
||||
// _ => return Err("Cannot create call from empty list"),
|
||||
// };
|
||||
// let args: Vec<_> = content.collect();
|
||||
// dbg!(args);
|
||||
|
||||
// Ok(Call {
|
||||
// name,
|
||||
// args: Vec::new(),
|
||||
// })
|
||||
// }
|
||||
|
||||
pub fn compile(ast: parser::ast::AST, data: &mut Data) -> Result<(), &str> {
|
||||
let mut iter = ast.body.into_iter().peekable();
|
||||
while let Some(node) = iter.next() {
|
||||
match node {
|
||||
parser::ast::Node::Comment(_) => {}
|
||||
parser::ast::Node::String(_) => return Err("Unexpected string on top level"),
|
||||
parser::ast::Node::Number(_) => return Err("Unexpected number on top level"),
|
||||
parser::ast::Node::Symbol(_) => return Err("Unexpected symbol on top level"),
|
||||
parser::ast::Node::Literal(_) => return Err("Unexpected literal on top level"),
|
||||
|
||||
parser::ast::Node::List(x) => {
|
||||
dbg!(&x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -4,7 +4,6 @@ use itertools::Itertools;
|
|||
#[derive(Debug)]
|
||||
pub enum Token {
|
||||
Comment(String),
|
||||
MultiLineComment(String),
|
||||
|
||||
Newline(String),
|
||||
Whitespace(String),
|
||||
|
@ -12,8 +11,9 @@ pub enum Token {
|
|||
LParen,
|
||||
RParen,
|
||||
|
||||
StringLiteral(String),
|
||||
String(String),
|
||||
Number(String),
|
||||
Symbol(String),
|
||||
Literal(String),
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,11 @@ impl hence::assembler::ToCode for Token {
|
|||
fn to_code(&self) -> String {
|
||||
match self {
|
||||
Token::Comment(x) => format!(";;{x}"),
|
||||
Token::MultiLineComment(x) => format!("#|{x}|#"),
|
||||
Token::Newline(x) | Token::Whitespace(x) => x.clone(),
|
||||
Token::LParen => "(".to_string(),
|
||||
Token::RParen => ")".to_string(),
|
||||
Token::StringLiteral(x) => format!("\"{x}\""),
|
||||
Token::Number(x) | Token::Literal(x) => x.clone(),
|
||||
Token::String(x) => format!("\"{x}\""),
|
||||
Token::Number(x) | Token::Symbol(x) | Token::Literal(x) => x.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,12 +66,26 @@ pub fn lex(source: String) -> Result<Vec<Token>, String> {
|
|||
}
|
||||
'"' => {
|
||||
chars.next();
|
||||
tokens.push(Token::StringLiteral(
|
||||
tokens.push(Token::String(
|
||||
chars.by_ref().take_while(|c| *c != '"').collect(),
|
||||
));
|
||||
}
|
||||
_ if ch.is_numeric() => {
|
||||
tokens.push(Token::Number(
|
||||
chars
|
||||
.peeking_take_while(|c| c.is_alphanumeric())
|
||||
.collect::<String>(),
|
||||
));
|
||||
}
|
||||
':' => {
|
||||
chars.next();
|
||||
tokens.push(Token::Symbol(
|
||||
chars
|
||||
.peeking_take_while(|c| !c.is_whitespace() && *c != '(' && *c != ')')
|
||||
.collect(),
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
dbg!(ch);
|
||||
tokens.push(Token::Literal(
|
||||
chars
|
||||
.peeking_take_while(|c| !c.is_whitespace() && *c != '(' && *c != ')')
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
pub mod compiler;
|
||||
pub mod lexer;
|
||||
pub mod parser;
|
||||
|
|
65
hencelisp/src/lib/parser.rs
Normal file
65
hencelisp/src/lib/parser.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use crate::lexer;
|
||||
|
||||
pub mod ast;
|
||||
|
||||
pub fn parse(tokens: Vec<lexer::Token>) -> Result<ast::AST, &'static str> {
|
||||
let mut iter = tokens.into_iter().peekable();
|
||||
let mut body: Vec<ast::Node> = Vec::new();
|
||||
|
||||
while let Some(token) = iter.peek() {
|
||||
match token {
|
||||
lexer::Token::Comment(x) => {
|
||||
body.push(ast::Node::Comment(x.trim().to_string()));
|
||||
iter.next();
|
||||
}
|
||||
lexer::Token::Newline(_) | lexer::Token::Whitespace(_) => {
|
||||
iter.next();
|
||||
}
|
||||
lexer::Token::LParen => {
|
||||
iter.next();
|
||||
let mut depth: usize = 1;
|
||||
body.push(ast::Node::List(
|
||||
parse(
|
||||
iter.by_ref()
|
||||
.take_while(|t| match t {
|
||||
lexer::Token::LParen => {
|
||||
depth += 1;
|
||||
true
|
||||
}
|
||||
lexer::Token::RParen => {
|
||||
depth -= 1;
|
||||
depth != 0
|
||||
}
|
||||
_ => true,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.unwrap()
|
||||
.body,
|
||||
));
|
||||
}
|
||||
lexer::Token::RParen => return Err("Unexpected right parenthesis"),
|
||||
lexer::Token::String(x) => {
|
||||
body.push(ast::Node::String(x.clone()));
|
||||
iter.next();
|
||||
}
|
||||
lexer::Token::Number(x) => {
|
||||
body.push(ast::Node::Number(match num_parse::parse_int(x) {
|
||||
Some(y) => y,
|
||||
_ => return Err("Error parsing number"),
|
||||
}));
|
||||
iter.next();
|
||||
}
|
||||
lexer::Token::Symbol(x) => {
|
||||
body.push(ast::Node::Symbol(x.clone()));
|
||||
iter.next();
|
||||
}
|
||||
lexer::Token::Literal(x) => {
|
||||
body.push(ast::Node::Literal(x.clone()));
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ast::AST { body })
|
||||
}
|
30
hencelisp/src/lib/parser/ast.rs
Normal file
30
hencelisp/src/lib/parser/ast.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use hence;
|
||||
use itertools::Itertools;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Node {
|
||||
Comment(String),
|
||||
List(Vec<Node>),
|
||||
String(String),
|
||||
Number(i32),
|
||||
Symbol(String),
|
||||
Literal(String),
|
||||
}
|
||||
|
||||
impl hence::assembler::ToCode for Node {
|
||||
fn to_code(&self) -> String {
|
||||
match self {
|
||||
Node::Comment(x) => format!(";; {x}"),
|
||||
Node::List(x) => format!("({})", x.iter().map(|n| n.to_code()).join(" ")),
|
||||
Node::String(x) => format!("\"{x}\""),
|
||||
Node::Number(x) => x.to_string(),
|
||||
Node::Symbol(x) => format!(":{x}"),
|
||||
Node::Literal(x) => x.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AST {
|
||||
pub body: Vec<Node>,
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
Reference in a new issue