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",
|
"clap",
|
||||||
"hence",
|
"hence",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
"num-parse",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
;; test module
|
;; main function
|
||||||
(module test
|
(defun main ()
|
||||||
"Main module"
|
"Program entrypoint"
|
||||||
(defun main ()
|
(let ((x (+ 40 2))))
|
||||||
"Program entrypoint"
|
(debug x))
|
||||||
(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> {
|
fn resolve_number(&self, data: &mut assembler::Data) -> Result<u16, String> {
|
||||||
match self {
|
match self {
|
||||||
Arg::String(x) => {
|
Arg::String(x) => {
|
||||||
|
|
|
@ -9,10 +9,10 @@ pub trait ToCode {
|
||||||
fn to_code(&self) -> String;
|
fn to_code(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ByteResolvable {
|
pub trait ByteResolvable<T> {
|
||||||
fn resolve_number(&self, data: &mut Data) -> Result<u16, String>;
|
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)]
|
#[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 iter = tokens.iter().peekable();
|
||||||
let mut body: Vec<ast::Node> = Vec::new();
|
let mut body: Vec<ast::Node> = Vec::new();
|
||||||
|
|
||||||
while let Some(token) = iter.peek() {
|
while let Some(&token) = iter.peek() {
|
||||||
match token {
|
match token {
|
||||||
lexer::Token::Comment(x) => {
|
lexer::Token::Comment(x) => {
|
||||||
body.push(ast::Node::Comment(x.trim().to_string()));
|
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(_) => {
|
lexer::Token::Whitespace(_) | lexer::Token::Newline(_) => {
|
||||||
iter.next();
|
iter.next();
|
||||||
}
|
}
|
||||||
_ => return Err("Unexspected token"),
|
_ => return Err("Unexpected token"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,4 @@ path = "src/bin/main.rs"
|
||||||
hence = { path = "../hence" }
|
hence = { path = "../hence" }
|
||||||
clap = { version = "3.2.12", features = ["derive"] }
|
clap = { version = "3.2.12", features = ["derive"] }
|
||||||
itertools = "0.10.3"
|
itertools = "0.10.3"
|
||||||
|
num-parse = "0.1.2"
|
||||||
|
|
|
@ -16,6 +16,20 @@ enum Commands {
|
||||||
#[clap(value_parser)]
|
#[clap(value_parser)]
|
||||||
src: String,
|
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() {
|
fn main() {
|
||||||
|
@ -26,5 +40,20 @@ fn main() {
|
||||||
let tokens = lexer::lex(source).unwrap();
|
let tokens = lexer::lex(source).unwrap();
|
||||||
dbg!(tokens);
|
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)]
|
#[derive(Debug)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
Comment(String),
|
Comment(String),
|
||||||
MultiLineComment(String),
|
|
||||||
|
|
||||||
Newline(String),
|
Newline(String),
|
||||||
Whitespace(String),
|
Whitespace(String),
|
||||||
|
@ -12,8 +11,9 @@ pub enum Token {
|
||||||
LParen,
|
LParen,
|
||||||
RParen,
|
RParen,
|
||||||
|
|
||||||
StringLiteral(String),
|
String(String),
|
||||||
Number(String),
|
Number(String),
|
||||||
|
Symbol(String),
|
||||||
Literal(String),
|
Literal(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,11 @@ impl hence::assembler::ToCode for Token {
|
||||||
fn to_code(&self) -> String {
|
fn to_code(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Token::Comment(x) => format!(";;{x}"),
|
Token::Comment(x) => format!(";;{x}"),
|
||||||
Token::MultiLineComment(x) => format!("#|{x}|#"),
|
|
||||||
Token::Newline(x) | Token::Whitespace(x) => x.clone(),
|
Token::Newline(x) | Token::Whitespace(x) => x.clone(),
|
||||||
Token::LParen => "(".to_string(),
|
Token::LParen => "(".to_string(),
|
||||||
Token::RParen => ")".to_string(),
|
Token::RParen => ")".to_string(),
|
||||||
Token::StringLiteral(x) => format!("\"{x}\""),
|
Token::String(x) => format!("\"{x}\""),
|
||||||
Token::Number(x) | Token::Literal(x) => x.clone(),
|
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();
|
chars.next();
|
||||||
tokens.push(Token::StringLiteral(
|
tokens.push(Token::String(
|
||||||
chars.by_ref().take_while(|c| *c != '"').collect(),
|
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(
|
tokens.push(Token::Literal(
|
||||||
chars
|
chars
|
||||||
.peeking_take_while(|c| !c.is_whitespace() && *c != '(' && *c != ')')
|
.peeking_take_while(|c| !c.is_whitespace() && *c != '(' && *c != ')')
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
|
pub mod compiler;
|
||||||
pub mod lexer;
|
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