Create a simple, Pascal like, string to help create messages for the parser. Added a function in the Parser that accepts many TokenTypes and reports the list of types if a sync is required.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
#ifndef PSTRING_H
|
||||
#define PSTRING_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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
|
||||
+75
-12
@@ -1,11 +1,13 @@
|
||||
#include "../includes/parser.h"
|
||||
#include "../includes/pstring.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user