diff --git a/includes/pstring.h b/includes/pstring.h new file mode 100644 index 0000000..3522d32 --- /dev/null +++ b/includes/pstring.h @@ -0,0 +1,15 @@ +#ifndef PSTRING_H +#define PSTRING_H + +#include +#include + +typedef struct pstring PString; + +PString* CreateString(void); +void StringAppend(const char* text, PString* string); +void StringFree(PString* string); +void StringTruncate(PString* string); +char* StringToCString(PString* string); + +#endif \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index 3ed20fd..b97beec 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,11 +1,13 @@ #include "../includes/parser.h" +#include "../includes/pstring.h" #include +#define ParserExpects(...) ParserExpectList(sizeof((TokenType[]){__VA_ARGS__})/sizeof(TokenType), __VA_ARGS__) + static Array* Tokens; size_t ParserIndex = 0; -const size_t MessageBufferLength = 2048 * sizeof(char); -char* MessageBuffer; +PString* MessageString; jmp_buf ParserSyncPointBuffer; @@ -18,6 +20,7 @@ void ParserHandleKeyword(Keywords keyword); void ParserHandleMnemonic(Mnemonics mnemonic); void ParserExpectParameter(Instruction* inst); Token* ParserExpect(TokenType type); +Token* ParserExpectList(int count, ...); Token* ParserWant(TokenType type); void ParserExpectLineEnd(void); void ParserSync(char* format, ...); @@ -26,8 +29,7 @@ void ParserSyncMessage(char* message); Instruction* ParserCreateInstruction(void); Instructions* ParseTokens(Array* tokens) { - MessageBuffer = malloc(MessageBufferLength); - + MessageString = CreateString(); Tokens = tokens; (void) setjmp(ParserSyncPointBuffer); @@ -53,11 +55,11 @@ Instructions* ParseTokens(Array* tokens) { void ParserSync(char* format, ...) { va_list args; - va_start (args, format); + va_start(args, format); vfprintf(stderr, format, args); - va_end (args); + va_end(args); ParserIgnoreLine(); @@ -107,7 +109,7 @@ void ParserHandleMnemonic(Mnemonics mnemonic) { case ADD: inst->ParameterCount = 2; - ParserExpectParameter(inst); + PARSER_EXPECT_LIST(LineEnd, Colon, Comma); break; default: @@ -118,11 +120,15 @@ void ParserHandleMnemonic(Mnemonics mnemonic) { void ParserExpectParameter(Instruction* inst) { if (ParserAtEnd()) return; + Token* token = ParserPeek(); + if (token->Type == Keyword) { - bool isPointer = ParserWant(OpenBracket) != NULL; + } - Token* token = ParserAdvance(); + inst->Parameters[0].Pointer = ParserWant(OpenBracket) != NULL; + + token = ParserAdvance(); if (token->Type == Number) { inst->Parameters[0].Type = Number; @@ -136,10 +142,18 @@ void ParserExpectParameter(Instruction* inst) { inst->Parameters[0].Type = Register; inst->Parameters[0].Value.Register = token->Value.Register; } - else ParserSyncMessage("No valid parameter found."); + else ParserSyncMessage("No valid parameter found 1."); + + if (inst->Parameters[0].Pointer) ParserExpect(CloseBracket); if (inst->ParameterCount == 1) return; + ParserExpect(Comma); + + if (!inst->Parameters[0].Pointer) inst->Parameters[1].Pointer = ParserWant(OpenBracket) != NULL; + + token = ParserAdvance(); + if (token->Type == Symbol) { inst->Parameters[1].Type = Symbol; inst->Parameters[1].Value.Name = token->Value.String; @@ -148,7 +162,9 @@ void ParserExpectParameter(Instruction* inst) { inst->Parameters[1].Type = Register; inst->Parameters[1].Value.Register = token->Value.Register; } - else ParserSyncMessage("No valid parameter found."); + else ParserSyncMessage("No valid parameter found 2."); + + if (inst->Parameters[1].Pointer) ParserExpect(CloseBracket); } Token* ParserExpect(TokenType type) { @@ -163,13 +179,60 @@ Token* ParserExpect(TokenType type) { return token; } -Token* ParserWant(TokenType type) { +Token* ParserExpectList(int count, ...) { if (ParserAtEnd()) return NULL; Token* token = ParserAdvance(); + va_list args; + va_start(args, count); + + for(int i = 0; i < count; i++) { + TokenType expect = va_arg(args, TokenType); + + if(token->Type == expect) { + va_end(args); + + return token; + } + } + //Report the error and sync the parser. + va_end(args); + + va_start(args, count); + + char buffer[32] = { 0 }; + StringTruncate(MessageString); + + StringAppend("Expected ", MessageString); + + for(int i = 0; i < count; i++) { + TokenType expect = va_arg(args, TokenType); + + TokenTypeStringify(expect, buffer); + + //Are we at the end? + if (i + 1 >= count) { + StringAppend("or ", MessageString); + StringAppend(buffer, MessageString); + } + else { + StringAppend(buffer, MessageString); + StringAppend(", ", MessageString); + } + } + + ParserSyncMessage(StringToCString(MessageString)); +} + +Token* ParserWant(TokenType type) { + if (ParserAtEnd()) return NULL; + + Token* token = ParserPeek(); if (!token || token->Type != type) return NULL; + (void) ParserAdvance(); + return token; } diff --git a/src/pstring.c b/src/pstring.c new file mode 100644 index 0000000..fc493b9 --- /dev/null +++ b/src/pstring.c @@ -0,0 +1,61 @@ +#include "../includes/pstring.h" + +#define DEFUALT_SSTRING_SIZE 64 + +struct pstring { + char* Buffer; + size_t Length; + size_t Capacity; +}; + +PString* CreateString(void) { + PString* string = calloc(1, sizeof(PString)); + + string->Buffer = calloc(DEFUALT_SSTRING_SIZE, sizeof(char)); + string->Capacity = DEFUALT_SSTRING_SIZE; + + return string; +} + +void StringResize(size_t additionalCapacity, PString* string) { + if (string->Capacity > string->Length + additionalCapacity) return; + + while(string->Length + additionalCapacity > string->Capacity) { + string->Buffer = realloc(string->Buffer, string->Capacity * 2); + + string->Capacity *= 2; + } +} + +void StringAppend(const char* text, PString* string) { + if (!string) return; + + size_t additional = strlen(text); + + StringResize(additional, string); + + memcpy(&string->Buffer[string->Length], text, additional); + + string->Length += additional; + string->Buffer[string->Length] = '\0'; +} + +void StringFree(PString* string) { + if (!string) return; + + free(string->Buffer); + free(string); +} + +char* StringToCString(PString* string) { + if (!string) return NULL; + + return string->Buffer; +} + +void StringTruncate(PString* string) { + if (!string) return; + + string->Length = 0; + string->Buffer[0] = '\0'; +} \ No newline at end of file diff --git a/src/token.c b/src/token.c index f19820c..f7c502a 100644 --- a/src/token.c +++ b/src/token.c @@ -110,7 +110,7 @@ void TokenTypeStringify(TokenType type, char buffer[32]) { strcpy(buffer, "FileEnd"); break; default: - snprintf(buffer, 32, "%c", type); + snprintf(buffer, 32, "'%c'", type); break; }