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