diff --git a/includes/token.h b/includes/token.h index dc3e6a1..b0c1813 100644 --- a/includes/token.h +++ b/includes/token.h @@ -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 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 555351f..88a09fa 100644 --- a/src/main.c +++ b/src/main.c @@ -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); } \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index ca54690..3ed20fd 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,4 +1,5 @@ #include "../includes/parser.h" +#include 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)); } \ No newline at end of file diff --git a/src/token.c b/src/token.c index 8561016..f19820c 100644 --- a/src/token.c +++ b/src/token.c @@ -83,4 +83,35 @@ char* TokenStringify(const struct _token* token) { if (strlen(buffer) > 0) strncpy(str, buffer, sizeof(buffer) - 1); 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; + } } \ No newline at end of file diff --git a/src/tokenizer.c b/src/tokenizer.c index 3634df9..60f5752 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -3,11 +3,14 @@ #include #include #include +#include #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++;