diff --git a/lang/src/tokeniser.asm b/lang/src/tokeniser.asm index 92a6a18..a5e548f 100644 --- a/lang/src/tokeniser.asm +++ b/lang/src/tokeniser.asm @@ -21,6 +21,8 @@ extern is_whitespace global tokeniser_init global tokeniser_print global find_lexeme +global expect_token +global unwrap_token ;; ============================= ;; Tokeniser functions @@ -702,3 +704,42 @@ find_lexeme: mov qword [rdi], TOKEN_COMMENT mov [rdi + 16], rax jmp .epilogue + +;; dil: expected token +expect_token: + push rbp + mov rbp, rsp + sub rsp, 0x30 + mov [rsp], dil + mov rax, [rel cursor] ; current cursor + mov [rsp + 8], rax + lea rdi, [rsp + 0x10] + call find_lexeme + mov rax, [rsp + 0x10] ; found token + mov dil, [rsp] ; expected token + cmp al, dil + je .matched + mov rdi, [rsp + 8] ; restore cursor + mov [rel cursor], rdi ; restore cursor + xor rax, rax + xor rdx, rdx + jmp .epilogue +.matched: + mov rax, [rsp + 0x18] ; lexeme pointer + mov rdx, [rsp + 0x20] ; lexeme length +.epilogue: + add rsp, 0x30 + pop rbp + ret + +;; dil: expected token +unwrap_token: + push rbp + mov rbp, rsp + call expect_token + test rax, rax + jz .panic + pop rbp + ret +.panic: + call panic diff --git a/lang/tests/bump.rs b/lang/tests/bump.rs index db39ffc..ca57ddf 100644 --- a/lang/tests/bump.rs +++ b/lang/tests/bump.rs @@ -1,9 +1,7 @@ #![feature(allocator_api, box_as_ptr)] -#[unsafe(no_mangle)] -extern "C" fn panic() -> ! { - panic!("Called panic from external code."); -} +#[path = "shared/shared.rs"] +mod util; unsafe extern "C" { unsafe fn bump_init(); diff --git a/lang/tests/int_to_str.rs b/lang/tests/int_to_str.rs index 87db35f..20f66a5 100644 --- a/lang/tests/int_to_str.rs +++ b/lang/tests/int_to_str.rs @@ -1,22 +1,7 @@ -#[unsafe(no_mangle)] -extern "C" fn panic() -> ! { - panic!("Called panic from external code."); -} +#[path = "shared/shared.rs"] +mod util; -#[repr(C)] -struct FFISlice { - ptr: *const u8, - len: usize, -} - -impl FFISlice { - fn as_slice(&self) -> &[u8] { - unsafe { core::slice::from_raw_parts(self.ptr, self.len) } - } - fn as_str(&self) -> &str { - unsafe { core::str::from_utf8_unchecked(self.as_slice()) } - } -} +use util::FFISlice; unsafe extern "C" { unsafe fn int_to_str2(value: isize, buffer: *mut u8, buffer_len: usize, radix: u8) -> FFISlice; diff --git a/lang/tests/shared/shared.rs b/lang/tests/shared/shared.rs new file mode 100644 index 0000000..ce87f4c --- /dev/null +++ b/lang/tests/shared/shared.rs @@ -0,0 +1,40 @@ +#[unsafe(no_mangle)] +extern "C" fn panic() -> ! { + panic!("Called panic from external code."); +} + +#[repr(C)] +#[derive(Debug, PartialEq, Eq)] +pub struct FFISlice { + pub ptr: *const u8, + pub len: usize, +} + +#[repr(transparent)] +#[derive(Debug, PartialEq, Eq)] +pub struct MaybeFFISlice { + inner: FFISlice, +} + +impl MaybeFFISlice { + pub fn is_none(&self) -> bool { + self.inner.ptr.is_null() + } + + pub fn into_option(self) -> Option { + if self.is_none() { + None + } else { + Some(self.inner) + } + } +} + +impl FFISlice { + pub fn as_slice(&self) -> &[u8] { + unsafe { core::slice::from_raw_parts(self.ptr, self.len) } + } + pub fn as_str(&self) -> &str { + unsafe { core::str::from_utf8_unchecked(self.as_slice()) } + } +} diff --git a/lang/tests/tokens.rs b/lang/tests/tokens.rs index 72ffb4c..8c594cb 100644 --- a/lang/tests/tokens.rs +++ b/lang/tests/tokens.rs @@ -1,7 +1,7 @@ -#[unsafe(no_mangle)] -extern "C" fn panic() -> ! { - panic!("Called panic from external code."); -} +#[path = "shared/shared.rs"] +mod util; + +use util::*; #[derive(Debug)] struct Lexeme(u8, &'static str); @@ -55,6 +55,8 @@ unsafe extern "C" { unsafe fn skip_whitespace() -> (); unsafe fn find_lexeme() -> LexemeRaw; + unsafe fn expect_token(token: u8) -> MaybeFFISlice; + unsafe fn unwrap_token(token: u8) -> FFISlice; static mut LEXEMES: *const u8; static mut LEXEME_LENS: usize; @@ -171,6 +173,14 @@ fn main() { ] ); + eprint!("Initializing tokeniser.. "); + tokeniser_init(c"tests/tokens/function.l".as_ptr()); + eprintln!("ok."); + + assert_eq!(expect_token(2).into_option(), None); + assert_eq!(expect_token(4).into_option().unwrap().as_str(), "fn"); + assert_eq!(unwrap_token(30).as_str(), "my-function"); + eprint!("Initializing tokeniser.. "); tokeniser_init(c"tests/tokens/comment.l".as_ptr()); eprintln!("ok.");