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 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
@@ -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
|
||||||
@@ -16,6 +16,7 @@ typedef enum {
|
|||||||
Register,
|
Register,
|
||||||
Mnemonic,
|
Mnemonic,
|
||||||
Keyword,
|
Keyword,
|
||||||
|
Label,
|
||||||
LineEnd = '\n',
|
LineEnd = '\n',
|
||||||
Colon = ':',
|
Colon = ':',
|
||||||
Comma = ',',
|
Comma = ',',
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
+22
-5
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user