Added back a way to stringify the TokenType. Updated the way the Parser syncs and added the start of parsing of opcodes.
This commit is contained in:
@@ -51,5 +51,6 @@ extern const Token TokenEmpty;
|
||||
|
||||
Token* TokenCreate(TokenType type, int lineNumber, int columnNumber, bool resolved);
|
||||
char* TokenStringify(const Token* token);
|
||||
void TokenTypeStringify(TokenType type, char buffer[32]);
|
||||
|
||||
#endif
|
||||
+6
-1
@@ -4,6 +4,9 @@
|
||||
#include "../includes/opcodes.h"
|
||||
#include "../includes/parser.h"
|
||||
|
||||
//For color out puts in the shell
|
||||
//https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* file;
|
||||
size_t count;
|
||||
@@ -28,6 +31,7 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
for(size_t i = 0; i < tokens->Size; i++) {
|
||||
Token* token = tokens->Items[i];
|
||||
|
||||
@@ -45,6 +49,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
//(void) ParseTokens(tokens);
|
||||
(void) ParseTokens(tokens);
|
||||
}
|
||||
+101
-7
@@ -1,4 +1,5 @@
|
||||
#include "../includes/parser.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
static Array* Tokens;
|
||||
|
||||
@@ -9,13 +10,20 @@ char* MessageBuffer;
|
||||
jmp_buf ParserSyncPointBuffer;
|
||||
|
||||
Token* ParserAdvance(void);
|
||||
Token* ParserPeek(void);
|
||||
void ParserIgnoreLine(void);
|
||||
bool ParserAtEnd(void);
|
||||
void ParserHandleKeyword(Keywords keyword);
|
||||
|
||||
void ParserHandleMnemonic(Mnemonics mnemonic);
|
||||
void ParserExpectParameter(Instruction* inst);
|
||||
Token* ParserExpect(TokenType type);
|
||||
Token* ParserWant(TokenType type);
|
||||
void ParserExpectLineEnd(void);
|
||||
void ParserSync(Token* got, char* message);
|
||||
void ParserSync(char* format, ...);
|
||||
void ParserSyncExpect(TokenType expected, TokenType found);
|
||||
void ParserSyncMessage(char* message);
|
||||
Instruction* ParserCreateInstruction(void);
|
||||
|
||||
Instructions* ParseTokens(Array* tokens) {
|
||||
MessageBuffer = malloc(MessageBufferLength);
|
||||
@@ -31,6 +39,9 @@ Instructions* ParseTokens(Array* tokens) {
|
||||
case Keyword:
|
||||
ParserHandleKeyword(token->Value.Keyword);
|
||||
break;
|
||||
case Mnemonic:
|
||||
ParserHandleMnemonic(token->Value.Mnemonic);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -39,18 +50,38 @@ Instructions* ParseTokens(Array* tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ParserSync(Token* got, char* message) {
|
||||
char* str = TokenStringify(got);
|
||||
void ParserSync(char* format, ...) {
|
||||
va_list args;
|
||||
|
||||
fprintf(stderr, "[Line %d] %s but got %s.\n", got->LineNumber, message, str);
|
||||
va_start (args, format);
|
||||
|
||||
free(str);
|
||||
vfprintf(stderr, format, args);
|
||||
|
||||
va_end (args);
|
||||
|
||||
ParserIgnoreLine();
|
||||
|
||||
longjmp(ParserSyncPointBuffer, 0);
|
||||
}
|
||||
|
||||
void ParserSyncExpect(TokenType expected, TokenType found) {
|
||||
char expectedName[32] = { 0 };
|
||||
char foundName[32] = { 0 };
|
||||
|
||||
TokenTypeStringify(expected, expectedName);
|
||||
TokenTypeStringify(found, foundName);
|
||||
|
||||
Token* current = ParserPeek();
|
||||
|
||||
ParserSync("[Line %d] Expected %s but got %s\n", current->LineNumber, expectedName, foundName);
|
||||
}
|
||||
|
||||
void ParserSyncMessage(char* message) {
|
||||
Token* current = ParserPeek();
|
||||
|
||||
ParserSync("[Line %d] %s\n", current->LineNumber, message);
|
||||
}
|
||||
|
||||
void ParserHandleKeyword(Keywords keyword) {
|
||||
Token* namespace = NULL;
|
||||
|
||||
@@ -67,13 +98,66 @@ void ParserHandleKeyword(Keywords keyword) {
|
||||
}
|
||||
}
|
||||
|
||||
void ParserHandleMnemonic(Mnemonics mnemonic) {
|
||||
Instruction* inst = ParserCreateInstruction();
|
||||
inst->Inst.Opcode = mnemonic;
|
||||
inst->IsOpcode = true;
|
||||
|
||||
switch(mnemonic) {
|
||||
case ADD:
|
||||
inst->ParameterCount = 2;
|
||||
|
||||
ParserExpectParameter(inst);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ParserExpectParameter(Instruction* inst) {
|
||||
if (ParserAtEnd()) return;
|
||||
|
||||
|
||||
|
||||
bool isPointer = ParserWant(OpenBracket) != NULL;
|
||||
|
||||
Token* token = ParserAdvance();
|
||||
|
||||
if (token->Type == Number) {
|
||||
inst->Parameters[0].Type = Number;
|
||||
inst->Parameters[0].Value.Number = token->Value.Number;
|
||||
}
|
||||
else if (token->Type == Symbol) {
|
||||
inst->Parameters[0].Type = Symbol;
|
||||
inst->Parameters[0].Value.Name = token->Value.String;
|
||||
}
|
||||
else if (token->Type == Register) {
|
||||
inst->Parameters[0].Type = Register;
|
||||
inst->Parameters[0].Value.Register = token->Value.Register;
|
||||
}
|
||||
else ParserSyncMessage("No valid parameter found.");
|
||||
|
||||
if (inst->ParameterCount == 1) return;
|
||||
|
||||
if (token->Type == Symbol) {
|
||||
inst->Parameters[1].Type = Symbol;
|
||||
inst->Parameters[1].Value.Name = token->Value.String;
|
||||
}
|
||||
if (token->Type == Register) {
|
||||
inst->Parameters[1].Type = Register;
|
||||
inst->Parameters[1].Value.Register = token->Value.Register;
|
||||
}
|
||||
else ParserSyncMessage("No valid parameter found.");
|
||||
}
|
||||
|
||||
Token* ParserExpect(TokenType type) {
|
||||
if (ParserAtEnd()) return NULL;
|
||||
|
||||
Token* token = ParserAdvance();
|
||||
|
||||
if (token->Type != type) {
|
||||
|
||||
ParserSyncExpect(type, token->Type);
|
||||
}
|
||||
|
||||
return token;
|
||||
@@ -95,7 +179,7 @@ void ParserExpectLineEnd(void) {
|
||||
Token* token = ParserAdvance();
|
||||
|
||||
if (token->Type != LineEnd && token->Type != FileEnd) {
|
||||
ParserSync(token, "Expected end of line or file");
|
||||
ParserSyncMessage("Expected end of line or file.");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -120,6 +204,16 @@ Token* ParserAdvance() {
|
||||
return next;
|
||||
}
|
||||
|
||||
Token* ParserPeek(void) {
|
||||
if (ParserAtEnd()) return (Token*) ArrayPeek(Tokens);
|
||||
|
||||
return (Token*) ArrayIndex(Tokens, ParserIndex);
|
||||
}
|
||||
|
||||
bool ParserAtEnd() {
|
||||
return ParserIndex >= Tokens->Size;
|
||||
}
|
||||
|
||||
Instruction* ParserCreateInstruction(void) {
|
||||
return calloc(1, sizeof(Instruction));
|
||||
}
|
||||
+31
@@ -84,3 +84,34 @@ char* TokenStringify(const struct _token* token) {
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void TokenTypeStringify(TokenType type, char buffer[32]) {
|
||||
if (!buffer) return;
|
||||
|
||||
memset(buffer, '\0', 32);
|
||||
|
||||
switch(type) {
|
||||
case Empty:
|
||||
strcpy(buffer, "Empty");
|
||||
break;
|
||||
case String:
|
||||
strcpy(buffer, "String");
|
||||
break;
|
||||
case Number:
|
||||
strcpy(buffer, "Number");
|
||||
break;
|
||||
case Symbol:
|
||||
strcpy(buffer, "Symbol");
|
||||
break;
|
||||
case LineEnd:
|
||||
strcpy(buffer, "LineEnd");
|
||||
break;
|
||||
case FileEnd:
|
||||
strcpy(buffer, "FileEnd");
|
||||
break;
|
||||
default:
|
||||
snprintf(buffer, 32, "%c", type);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
+20
-4
@@ -3,11 +3,14 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#define MAXWORDLENGTH 1024
|
||||
|
||||
static Array* Tokens;
|
||||
|
||||
jmp_buf TokenizerSyncPointBuffer;
|
||||
|
||||
const char* SourceCode;
|
||||
size_t SourceCodeLength = 0;
|
||||
size_t SourceCodeIndex = 0;
|
||||
@@ -25,6 +28,7 @@ void TokenizerExpectWord(void);
|
||||
void TokenizerExpectString(void);
|
||||
void TokenizerExpectNumber(void);
|
||||
void TokenizerIgnoreLine();
|
||||
void TokenizerSync(char* message);
|
||||
|
||||
Array* Tokenize(const char* sourceCode) {
|
||||
Tokens = ArrayCreate();
|
||||
@@ -32,6 +36,8 @@ Array* Tokenize(const char* sourceCode) {
|
||||
SourceCodeLength = strlen(sourceCode);
|
||||
SourceCode = sourceCode;
|
||||
|
||||
(void) setjmp(TokenizerSyncPointBuffer);
|
||||
|
||||
while(!TokenizerAtEnd()) {
|
||||
char c = PeekTokenizer();
|
||||
|
||||
@@ -102,7 +108,6 @@ Array* Tokenize(const char* sourceCode) {
|
||||
case ')':
|
||||
case '[':
|
||||
case ']':
|
||||
//case ':':
|
||||
case ',':
|
||||
token = TokenCreate((TokenType)c, SourceLineNumber, SourceColumnNumber, true);
|
||||
|
||||
@@ -122,6 +127,14 @@ Array* Tokenize(const char* sourceCode) {
|
||||
return Tokens;
|
||||
}
|
||||
|
||||
void TokenizerSync(char* message) {
|
||||
fprintf(stderr, "[Line %d] %s\n", SourceLineNumber, message);
|
||||
|
||||
TokenizerIgnoreLine();
|
||||
|
||||
longjmp(TokenizerSyncPointBuffer, 0);
|
||||
}
|
||||
|
||||
void TokenizerExpectNumber(void) {
|
||||
char word[256] = { 0 };
|
||||
int wordLength = 0;
|
||||
@@ -151,7 +164,8 @@ void TokenizerExpectNumber(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (wordLength == 255) break; //Sync, error etc here at some point.
|
||||
if (wordLength == 255)
|
||||
TokenizerSync("Number exceeded the maximum character length.");
|
||||
|
||||
word[wordLength] = c;
|
||||
wordLength++;
|
||||
@@ -196,7 +210,8 @@ void TokenizerExpectWord() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (wordLength == 255) break; //Sync, error etc here at some point.
|
||||
if (wordLength == 255)
|
||||
TokenizerSync("Word exceeded the maximum character length.");
|
||||
|
||||
word[wordLength] = c;
|
||||
wordLength++;
|
||||
@@ -267,7 +282,8 @@ void TokenizerExpectString(void) {
|
||||
if (c != '\\') AdvanceTokenizer();
|
||||
}
|
||||
|
||||
if (wordLength == 255) break; //Sync, error etc here at some point.
|
||||
if (wordLength == 255)
|
||||
TokenizerSync("String exceeded the maximum character length.");
|
||||
|
||||
word[wordLength] = c;
|
||||
wordLength++;
|
||||
|
||||
Reference in New Issue
Block a user