Updated the parser to be able to correctly sync via a longjmp. Fixed a few bugs in the tokenizer, like not allowing underscores in symbol / label names and taught it how to detect a label declaration. Fixed the code that gets the register name.

This commit is contained in:
2025-06-26 23:24:03 -05:00
parent 3a5788f4ab
commit 428556a7a1
9 changed files with 141 additions and 63 deletions
+12 -12
View File
@@ -1,22 +1,22 @@
namespace string 67; my string namespace here namespace string 67; my string namespace here
namespace text "some string in the middle of nowhere" namespace text "some string in the middle of nowhere";do you do this?
word FRAMEBUFFER 0x00200500 word FRAMEBUFFER 0x00200500
asciiz Msg "Hello World!" asciiz Msg "Hello World!"
; fn effectively is an "Append to Namespace" command, ie string + "." + _start ; fn effectively is an "Append to Namespace" command, ie string + "." + _start
fn _start: fn _start:;do you do this?
mov FRAMEBUFFER, r32 ; imm, r mov FRAMEBUFFER, r32; imm, r
mov msg, r1 ; imm, r mov msg, r1 ; imm, r
call strlen ; result into r2 call strlen ; result into r2
mov 0, r4 ; counter mov 0, r4 ; counter
loop: loop:
mov byte [r1], r3 ; read char into r3 mov byte [r1], r3 ; read char into r3
cmp r3, 0 ; NUL byte? cmp r3, 0; NUL byte?
je end jz end
mov byte r3, [r32] ; Write char to frame buffer mov byte r3, [r32]; Write char to frame buffer
inc r32 ; Next space in framebuffer add 1, r32 ; Next space in framebuffer
inc r4 ; inc counter add 1, r4 ; inc counter
inc r1 ; inc pointer to msg add 1, r1 ; inc pointer to msg
jmp loop jmp loop
end: ;At the moment this just writes Msg to the framebuffer. end: ;At the moment this just writes Msg to the framebuffer.
ret ret
@@ -29,9 +29,9 @@ fn strlen:
loop: loop:
mov byte [r1], r3 ; mov char into r3 mov byte [r1], r3 ; mov char into r3
cmp r3, 0 ; NUL byte? cmp r3, 0 ; NUL byte?
je end jz end
inc r1 ; next char add 1, r1 ; next char
inc r2 ; length++ add 1, r2 ; length++
jmp loop jmp loop
end: end:
ret ret
+21 -1
View File
@@ -3,15 +3,35 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <setjmp.h>
#include "dictionary.h" #include "dictionary.h"
#include "opcodes.h" #include "opcodes.h"
#include "token.h" #include "token.h"
#include "array.h" #include "array.h"
#include "keywords.h" #include "keywords.h"
typedef struct _instruction Instruction;
typedef Array Instructions; typedef Array Instructions;
typedef struct parameter {
bool Pointer;
TokenType Type;
union {
char* Name;
Registers Register;
uint32_t Number;
} Value;
} Parameter;
typedef struct instruction {
bool IsOpcode;
union {
Mnemonics Opcode;
Keywords Directive;
} Inst;
int ParameterCount;
Parameter Parameters[2];
} Instruction;
Instructions* ParseTokens(Array* tokens); Instructions* ParseTokens(Array* tokens);
#endif #endif
+1
View File
@@ -16,6 +16,7 @@ typedef enum {
Register, Register,
Mnemonic, Mnemonic,
Keyword, Keyword,
Label,
LineEnd = '\n', LineEnd = '\n',
Colon = ':', Colon = ':',
Comma = ',', Comma = ',',
+1 -1
View File
@@ -5,6 +5,6 @@
#include "dictionary.h" #include "dictionary.h"
#include "token.h" #include "token.h"
Array* Tokenize(const char* text, Dictionary** variables); Array* Tokenize(const char* text);
#endif #endif
+7 -17
View File
@@ -8,8 +8,6 @@ int main(int argc, char** argv) {
char* file; char* file;
size_t count; size_t count;
//gcc -o test src/main.c src/futil.c src/dictionary.c src/tokenizer.c src/token.c src/array.c -g
if (argc <= 1) { if (argc <= 1) {
printf("Usage: assm <file.asm>\n"); printf("Usage: assm <file.asm>\n");
@@ -22,20 +20,15 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
Dictionary* variables = DictionaryCreate(); Array* tokens = Tokenize(file);
Array* tokens = Tokenize(file, &variables);
if (tokens->Size == 0) { if (tokens->Size == 0) {
printf("No tokens\n"); printf("No tokens\n");
return 0; return 0;
} }
/*
char* buffer;
char type[32];
for(int i = 0; i < tokens->Size; i++) { for(size_t i = 0; i < tokens->Size; i++) {
Token* token = tokens->Items[i]; Token* token = tokens->Items[i];
if (token->Type == LineEnd) { if (token->Type == LineEnd) {
@@ -44,17 +37,14 @@ int main(int argc, char** argv) {
continue; continue;
} }
//StringifyTokenType(token->Type, type); char* str = TokenStringify(token);
buffer = TokenStringify(token);
if (buffer) { printf("%s ", str);
printf("%s ", buffer);
free(buffer); free(str);
}
} }
printf("\n"); printf("\n");
*/
(void) ParseTokens(tokens); //(void) ParseTokens(tokens);
} }
+21 -4
View File
@@ -3,7 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define OPCODE_COUNT 29 #define OPCODE_COUNT 30
struct _instruction { struct _instruction {
char* Name; char* Name;
@@ -24,6 +24,7 @@ struct _instruction Instructions[OPCODE_COUNT] = {
{ "shr", SHR }, { "shr", SHR },
{ "nop", NOP }, { "nop", NOP },
{ "cmp", CMP }, { "cmp", CMP },
{ "jmp", JMP },
{ "jz", JZ }, { "jz", JZ },
{ "jg", JG }, { "jg", JG },
{ "jl", JL }, { "jl", JL },
@@ -56,10 +57,26 @@ void GetMnemonicText(Mnemonics mnemonic, char buffer[12]) {
void GetRegisterText(Registers reg, char buffer[5]) { void GetRegisterText(Registers reg, char buffer[5]) {
memset(buffer, '\0', 5); memset(buffer, '\0', 5);
if (reg < R1 || reg > R32) return; switch(reg) {
case RBP:
buffer[0] = 'r'; buffer[0] = 'r';
buffer[1] = reg + 49; buffer[1] = 'b';
buffer[2] = 'p';
break;
case RSP:
buffer[0] = 'r';
buffer[1] = 's';
buffer[2] = 'p';
break;
case RIP:
buffer[0] = 'r';
buffer[1] = 'i';
buffer[2] = 'p';
break;
default:
snprintf(buffer, 5, "r%d", reg);
break;
}
} }
int IsOpcode(const char* text, Mnemonics* opcode) { int IsOpcode(const char* text, Mnemonics* opcode) {
+6 -3
View File
@@ -6,6 +6,8 @@ size_t ParserIndex = 0;
const size_t MessageBufferLength = 2048 * sizeof(char); const size_t MessageBufferLength = 2048 * sizeof(char);
char* MessageBuffer; char* MessageBuffer;
jmp_buf ParserSyncPointBuffer;
Token* ParserAdvance(void); Token* ParserAdvance(void);
void ParserIgnoreLine(void); void ParserIgnoreLine(void);
bool ParserAtEnd(void); bool ParserAtEnd(void);
@@ -20,6 +22,8 @@ Instructions* ParseTokens(Array* tokens) {
Tokens = tokens; Tokens = tokens;
(void) setjmp(ParserSyncPointBuffer);
while(!ParserAtEnd()) { while(!ParserAtEnd()) {
Token* token = ParserAdvance(); Token* token = ParserAdvance();
@@ -43,6 +47,8 @@ void ParserSync(Token* got, char* message) {
free(str); free(str);
ParserIgnoreLine(); ParserIgnoreLine();
longjmp(ParserSyncPointBuffer, 0);
} }
void ParserHandleKeyword(Keywords keyword) { void ParserHandleKeyword(Keywords keyword) {
@@ -54,9 +60,6 @@ void ParserHandleKeyword(Keywords keyword) {
namespace = ParserExpect(Symbol); namespace = ParserExpect(Symbol);
ParserExpectLineEnd(); ParserExpectLineEnd();
printf("Namespace `%s` seen\n", namespace->Value.String);
break; break;
} }
default: default:
+13 -2
View File
@@ -30,10 +30,20 @@ char* TokenStringify(const struct _token* token) {
return str; return str;
} }
else if (token->Type == Symbol) { else if (token->Type == Symbol) {
bufferSize = strlen(token->Value.String) + 1; // Add three for 2 backticks and a NUL byte.
bufferSize = strlen(token->Value.String) + 3;
str = calloc(bufferSize, sizeof(char)); str = calloc(bufferSize, sizeof(char));
strncpy(str, token->Value.String, bufferSize); snprintf(str, bufferSize, "`%s`", token->Value.String);
return str;
}
else if (token->Type == Label) {
// Add 2 for the colon and Nul byte.
bufferSize = strlen(token->Value.String) + 2;
str = calloc(bufferSize, sizeof(char));
snprintf(str, bufferSize, "%s:", token->Value.String);
return str; return str;
} }
@@ -63,6 +73,7 @@ char* TokenStringify(const struct _token* token) {
strcpy(str, "(LineEnd)"); strcpy(str, "(LineEnd)");
break; break;
case FileEnd: case FileEnd:
strcpy(str, "(FileEnd)");
break; break;
default: default:
sprintf(str, "%s", token->Value.Operator); sprintf(str, "%s", token->Value.Operator);
+58 -22
View File
@@ -15,6 +15,7 @@ int SourceLineNumber = 1;
int SourceColumnNumber = 1; int SourceColumnNumber = 1;
char PeekTokenizer(void); char PeekTokenizer(void);
char TokenizerLookAhead(void);
bool TryPopTokenizer(char* c); bool TryPopTokenizer(char* c);
bool TokenizerAtEnd(void); bool TokenizerAtEnd(void);
char AdvanceTokenizer(void); char AdvanceTokenizer(void);
@@ -23,9 +24,9 @@ bool BackTokenzier(void);
void TokenizerExpectWord(void); void TokenizerExpectWord(void);
void TokenizerExpectString(void); void TokenizerExpectString(void);
void TokenizerExpectNumber(void); void TokenizerExpectNumber(void);
void TokenizerIgnoreLine(void); void TokenizerIgnoreLine();
Array* Tokenize(const char* sourceCode, Dictionary** variables) { Array* Tokenize(const char* sourceCode) {
Tokens = ArrayCreate(); Tokens = ArrayCreate();
SourceCodeLength = strlen(sourceCode); SourceCodeLength = strlen(sourceCode);
@@ -36,6 +37,16 @@ Array* Tokenize(const char* sourceCode, Dictionary** variables) {
if (c == '\0') break; if (c == '\0') break;
if (c == ';') {
while(TryPopTokenizer(&c)) {
if (PeekTokenizer() != '\n') continue;
break;
}
continue;
}
if (isalpha(c)) { if (isalpha(c)) {
TokenizerExpectWord(); TokenizerExpectWord();
@@ -56,21 +67,32 @@ Array* Tokenize(const char* sourceCode, Dictionary** variables) {
continue; continue;
} }
if (c == ';') { if (c == '_') {
TokenizerIgnoreLine(); c = TokenizerLookAhead();
continue; if (isdigit(c) || isalpha(c) || c == '_')
TokenizerExpectWord();
else
c = '_';
} }
Token* token = NULL; Token* token = NULL;
switch(c) { switch(c) {
case '\n': case '\n':
token = (Token*) ArrayPeek(Tokens); {
//Is there a previous token and if so, was it a line break? Token* previousToken = (Token*) ArrayPeek(Tokens);
if (token && token->Type == LineEnd)
break; //Discard empty line. if (previousToken->Type == LineEnd) break;
__attribute__ ((fallthrough));
Token* token = TokenCreate(LineEnd, SourceLineNumber, SourceColumnNumber, true);
token->Value.Operator[0] = '\n';
ArrayAdd(Tokens, token);
break;
}
case '+': case '+':
case '-': case '-':
case '*': case '*':
@@ -80,7 +102,7 @@ Array* Tokenize(const char* sourceCode, Dictionary** variables) {
case ')': case ')':
case '[': case '[':
case ']': case ']':
case ':': //case ':':
case ',': case ',':
token = TokenCreate((TokenType)c, SourceLineNumber, SourceColumnNumber, true); token = TokenCreate((TokenType)c, SourceLineNumber, SourceColumnNumber, true);
@@ -106,7 +128,7 @@ void TokenizerExpectNumber(void) {
char c; char c;
while(TryPopTokenizer(&c)) { while(TryPopTokenizer(&c)) {
if (c == '\n') { if (c == '\n' || c == ';') {
BackTokenzier(); BackTokenzier();
break; break;
@@ -123,7 +145,11 @@ void TokenizerExpectNumber(void) {
continue; continue;
} }
if (!isxdigit(c)) break; if (!isxdigit(c)) {
BackTokenzier();
break;
}
if (wordLength == 255) break; //Sync, error etc here at some point. if (wordLength == 255) break; //Sync, error etc here at some point.
@@ -144,9 +170,10 @@ void TokenizerExpectWord() {
char word[256] = { 0 }; char word[256] = { 0 };
int wordLength = 0; int wordLength = 0;
char c; char c;
bool isLabel = false;
while(TryPopTokenizer(&c)) { while(TryPopTokenizer(&c)) {
if (c == '\n') { if (c == '\n' || c == ';') {
BackTokenzier(); BackTokenzier();
break; break;
@@ -156,13 +183,14 @@ void TokenizerExpectWord() {
break; break;
} }
if (c == ';') { if (c == ':') {
TokenizerIgnoreLine(); BackTokenzier();
isLabel = true;
break; break;
} }
if (ispunct(c)) { if (ispunct(c) && c != '_') {
BackTokenzier(); BackTokenzier();
break; break;
@@ -197,7 +225,7 @@ void TokenizerExpectWord() {
token->Value.Keyword = keyword; token->Value.Keyword = keyword;
} }
else { else {
token = TokenCreate(Symbol, SourceLineNumber, SourceColumnNumber, false); token = TokenCreate(isLabel ? Label : Symbol, SourceLineNumber, SourceColumnNumber, false);
token->Value.String = calloc(wordLength + 1, sizeof(char)); token->Value.String = calloc(wordLength + 1, sizeof(char));
@@ -213,7 +241,7 @@ void TokenizerExpectString(void) {
char c; char c;
while(TryPopTokenizer(&c)) { while(TryPopTokenizer(&c)) {
if (c == '\n') { if (c == '\n' || c == ';') {
BackTokenzier(); BackTokenzier();
break; break;
@@ -256,11 +284,12 @@ void TokenizerExpectString(void) {
} }
} }
void TokenizerIgnoreLine(void) { void TokenizerIgnoreLine() {
char c; char c;
while(TryPopTokenizer(&c)) { while(TryPopTokenizer(&c)) {
if (PeekTokenizer() == '\n') break; if (PeekTokenizer() != '\n') continue;
break;
} }
} }
@@ -268,6 +297,13 @@ char PeekTokenizer(void) {
return SourceCode[SourceCodeIndex]; return SourceCode[SourceCodeIndex];
} }
char TokenizerLookAhead(void) {
if (TokenizerAtEnd()) return '\0';
if (SourceCodeIndex + 1 > SourceCodeLength) return '\0';
return SourceCode[SourceCodeIndex + 1];
}
bool TryPopTokenizer(char* c) { bool TryPopTokenizer(char* c) {
*c = AdvanceTokenizer(); *c = AdvanceTokenizer();