Did stuff

This commit is contained in:
Dominic Grimm 2022-07-20 14:24:38 +02:00
parent dd23759f85
commit 2def36a617
No known key found for this signature in database
GPG key ID: A6C051C716D2CE65
13 changed files with 220 additions and 23 deletions

1
Cargo.lock generated
View file

@ -118,6 +118,7 @@ dependencies = [
"clap",
"hence",
"itertools",
"num-parse",
]
[[package]]

View file

@ -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))

View file

@ -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) => {

View file

@ -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)]

View file

@ -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"),
}
}

View file

@ -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"

View file

@ -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);
}
}
}

View 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(())
}

View file

@ -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 != ')')

View file

@ -1 +1,3 @@
pub mod compiler;
pub mod lexer;
pub mod parser;

View 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 })
}

View 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>,
}

View file

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}