This commit is contained in:
vanten-s 2024-08-08 21:53:27 +02:00
commit 60115d0612
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
7 changed files with 212 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

6
Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "lisp-8bit"
version = "0.1.0"
edition = "2021"
[dependencies]

13
shell.nix Normal file
View file

@ -0,0 +1,13 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell rec {
buildInputs = with pkgs; [
rustup
];
RUSTC_VERSION = "stable";
shellHook = ''
rustup default $RUSTC_VERSION
rustup component add rust-analyzer
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
'';
}

13
src/assembler.rs Normal file
View file

@ -0,0 +1,13 @@
use crate::parser::Instruction;
pub struct Assembler {
instruction: Instruction,
}
impl Assembler {
pub fn assemble(instruction: Instruction) -> Vec<u8> {
let assembler = Assembler { instruction };
todo!()
}
}

23
src/error.rs Normal file
View file

@ -0,0 +1,23 @@
#[derive(Clone, Debug, Hash)]
pub enum Error {
SyntaxError(SyntaxError),
}
#[derive(Clone, Debug, Hash)]
pub struct SyntaxError {
pub row: usize,
pub column: usize,
pub message: String,
}
pub type Result<T> = ::core::result::Result<T, Error>;
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::SyntaxError(e) => write!(f, "Error at: {}:{}. {}", e.row, e.column, e.message),
}
}
}
impl std::error::Error for Error {}

12
src/main.rs Normal file
View file

@ -0,0 +1,12 @@
mod assembler;
mod parser;
mod error;
pub use error::*;
fn main() {
let code = "(+ 1 2)".to_string();
dbg!(parser::Parser::parse(code).unwrap());
}

143
src/parser.rs Normal file
View file

@ -0,0 +1,143 @@
use crate::*;
#[derive(Debug)]
pub struct Parser {
row: usize,
column: usize,
lines: Vec<Vec<char>>,
}
#[derive(Debug)]
pub(crate) struct Instruction {
name: String,
arguments: Vec<Value>,
}
#[derive(Debug)]
enum Value {
Instruction(Instruction),
StringLiteral(String),
IntegerLiteral(usize),
Identifier(String),
}
impl Parser {
pub fn parse(stream: String) -> Result<Instruction> {
let mut parser = Parser {
row: 0,
column: 0,
lines: stream
.split('\n')
.map(|a| a.chars().collect::<Vec<_>>())
.collect::<Vec<_>>(),
};
parser.instruction()
}
fn increment(&mut self) -> Option<()> {
self.column += 1;
if self.column == self.lines[self.row].len() {
self.row += 1;
if self.row == self.lines.len() {
self.row -= 1;
self.column -= 1;
return None;
}
self.column = 0;
}
return Some(());
}
fn jump_whitespace(&mut self) -> Option<()> {
self.increment()?;
while self.lines[self.row][self.column].is_whitespace() {
self.increment()?;
}
Some(())
}
fn instruction(&mut self) -> Result<Instruction> {
if self.lines[self.row][self.column] != '(' {
return Err(Error::SyntaxError(SyntaxError {
row: self.row,
column: self.column,
message: "SyntaxError: Expected '('".to_string(),
}));
}
self.jump_whitespace();
let name = self.identifier()?;
let mut arguments = Vec::new();
while self.lines[self.row][self.column] != ')' {
match self.lines[self.row][self.column] {
'\"' => arguments.push(Value::StringLiteral(self.string_literal()?)),
'(' => arguments.push(Value::Instruction(self.instruction()?)),
character => {
if character.is_numeric() {
arguments.push(Value::IntegerLiteral(self.integer_literal()?));
} else {
arguments.push(Value::Identifier(self.identifier()?));
}
}
}
}
self.jump_whitespace();
return Ok(Instruction { name, arguments });
}
fn string_literal(&mut self) -> Result<String> {
self.increment();
let mut accumulator = String::new();
while self.lines[self.row][self.column] != '"' {
accumulator.push(self.lines[self.row][self.column]);
self.increment();
}
self.jump_whitespace();
Ok(accumulator)
}
fn integer_literal(&mut self) -> Result<usize> {
let mut accumulator = String::new();
while self.lines[self.row][self.column].is_numeric() {
accumulator.push(self.lines[self.row][self.column]);
self.increment();
}
self.jump_whitespace();
match accumulator.parse::<usize>() {
Ok(v) => Ok(v),
Err(_e) => Err(Error::SyntaxError(SyntaxError {
row: self.row,
column: self.column,
message: "Couldn't parse integer literal".to_string(),
})),
}
}
fn identifier(&mut self) -> Result<String> {
let mut accumulator = String::new();
let mut current = self.lines[self.row][self.column];
while !"()\"".contains(current) && !current.is_whitespace() {
accumulator.push(self.lines[self.row][self.column]);
self.increment();
current = self.lines[self.row][self.column];
}
self.jump_whitespace();
Ok(accumulator)
}
}