Immediates and labels not implemented yet, soon be there.

This commit is contained in:
Erin 2023-07-12 01:22:28 +02:00 committed by ondra05
parent 299e8e6759
commit b0b4022a85
2 changed files with 91 additions and 3 deletions

View file

@ -33,7 +33,6 @@ macros::impl_both!(
=> [NOP, ECALL],
);
pub trait Imm {
fn insert(&self, asm: &mut Assembler);
}

View file

@ -8,8 +8,12 @@ macro_rules! gen_text {
) => {
pub mod text {
use {
crate::{
Assembler,
macros::text::*,
},
lasso::{Rodeo, Spur},
logos::Logos,
logos::{Lexer, Logos, Span},
};
paste::paste!(literify::literify! {
@ -52,8 +56,93 @@ macro_rules! gen_text {
#[token(",")] PSep,
}
});
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ErrorKind {
UnexpectedToken,
InvalidToken,
UnexpectedEnd,
InvalidSymbol,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Error {
pub kind: ErrorKind,
pub span: Span,
}
pub fn assemble(asm: &mut Assembler, code: &str) -> Result<(), Error> {
fn next(lexer: &mut Lexer<Token>) -> Result<Token, ErrorKind> {
match lexer.next() {
Some(Ok(t)) => Ok(t),
Some(Err(())) => Err(ErrorKind::InvalidToken),
None => Err(ErrorKind::UnexpectedEnd),
}
}
#[inline(always)]
fn inner(asm: &mut Assembler, lexer: &mut Lexer<Token>) -> Result<(), ErrorKind> {
loop {
match lexer.next() {
Some(Ok(Token::Opcode(op))) => {
match op {
$(
$(hbbytecode::opcode::$opcode)|* => paste::paste!({
param_extract_iim!(lexer, $($param_i: $param_ty),*);
asm.[<i_param_ $ityn>](op, $($param_i),*);
}),
)*
_ => unreachable!(),
}
}
Some(Ok(Token::Label(_))) => {
todo!("Labels");
}
Some(Ok(Token::ISep)) => (),
Some(Ok(_)) => return Err(ErrorKind::UnexpectedToken),
Some(Err(())) => return Err(ErrorKind::InvalidToken),
None => return Ok(()),
}
}
}
let mut lexer = Token::lexer(code);
inner(asm, &mut lexer)
.map_err(|kind| Error { kind, span: lexer.span() })
}
}
};
}
pub(crate) use gen_text;
macro_rules! extract_pat {
($lexer:expr, $pat:pat) => {
let $pat = next($lexer)?
else { return Err(ErrorKind::UnexpectedToken) };
};
}
macro_rules! extract {
($lexer:expr, R, $id:ident) => {
extract_pat!($lexer, Token::Register($id));
};
($lexer:expr, I, $id:ident) => {
extract_pat!($lexer, Token::Integer($id));
};
($lexer:expr, u16, $id:ident) => {
extract_pat!($lexer, Token::Integer($id));
let $id = u16::try_from($id)
.map_err(|_| ErrorKind::InvalidToken)?;
};
}
macro_rules! param_extract_iim {
($lexer:expr, $($id:ident: $ty:ident)? $(, $($tt:tt)*)?) => {
$(extract!($lexer, $ty, $id);)?
$(
extract_pat!($lexer, Token::PSep);
param_extract_iim!($lexer, $($tt)*);
)?
};
}
pub(crate) use {extract, extract_pat, gen_text, param_extract_iim};