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/parser.h"
|
||||||
|
#include "../includes/pstring.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#define ParserExpects(...) ParserExpectList(sizeof((TokenType[]){__VA_ARGS__})/sizeof(TokenType), __VA_ARGS__)
|
||||||
|
|
||||||
static Array* Tokens;
|
static Array* Tokens;
|
||||||
|
|
||||||
size_t ParserIndex = 0;
|
size_t ParserIndex = 0;
|
||||||
const size_t MessageBufferLength = 2048 * sizeof(char);
|
PString* MessageString;
|
||||||
char* MessageBuffer;
|
|
||||||
|
|
||||||
jmp_buf ParserSyncPointBuffer;
|
jmp_buf ParserSyncPointBuffer;
|
||||||
|
|
||||||
@@ -18,6 +20,7 @@ void ParserHandleKeyword(Keywords keyword);
|
|||||||
void ParserHandleMnemonic(Mnemonics mnemonic);
|
void ParserHandleMnemonic(Mnemonics mnemonic);
|
||||||
void ParserExpectParameter(Instruction* inst);
|
void ParserExpectParameter(Instruction* inst);
|
||||||
Token* ParserExpect(TokenType type);
|
Token* ParserExpect(TokenType type);
|
||||||
|
Token* ParserExpectList(int count, ...);
|
||||||
Token* ParserWant(TokenType type);
|
Token* ParserWant(TokenType type);
|
||||||
void ParserExpectLineEnd(void);
|
void ParserExpectLineEnd(void);
|
||||||
void ParserSync(char* format, ...);
|
void ParserSync(char* format, ...);
|
||||||
@@ -26,8 +29,7 @@ void ParserSyncMessage(char* message);
|
|||||||
Instruction* ParserCreateInstruction(void);
|
Instruction* ParserCreateInstruction(void);
|
||||||
|
|
||||||
Instructions* ParseTokens(Array* tokens) {
|
Instructions* ParseTokens(Array* tokens) {
|
||||||
MessageBuffer = malloc(MessageBufferLength);
|
MessageString = CreateString();
|
||||||
|
|
||||||
Tokens = tokens;
|
Tokens = tokens;
|
||||||
|
|
||||||
(void) setjmp(ParserSyncPointBuffer);
|
(void) setjmp(ParserSyncPointBuffer);
|
||||||
@@ -53,11 +55,11 @@ Instructions* ParseTokens(Array* tokens) {
|
|||||||
void ParserSync(char* format, ...) {
|
void ParserSync(char* format, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start (args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
vfprintf(stderr, format, args);
|
vfprintf(stderr, format, args);
|
||||||
|
|
||||||
va_end (args);
|
va_end(args);
|
||||||
|
|
||||||
ParserIgnoreLine();
|
ParserIgnoreLine();
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ void ParserHandleMnemonic(Mnemonics mnemonic) {
|
|||||||
case ADD:
|
case ADD:
|
||||||
inst->ParameterCount = 2;
|
inst->ParameterCount = 2;
|
||||||
|
|
||||||
ParserExpectParameter(inst);
|
PARSER_EXPECT_LIST(LineEnd, Colon, Comma);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -118,11 +120,15 @@ void ParserHandleMnemonic(Mnemonics mnemonic) {
|
|||||||
void ParserExpectParameter(Instruction* inst) {
|
void ParserExpectParameter(Instruction* inst) {
|
||||||
if (ParserAtEnd()) return;
|
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) {
|
if (token->Type == Number) {
|
||||||
inst->Parameters[0].Type = Number;
|
inst->Parameters[0].Type = Number;
|
||||||
@@ -136,10 +142,18 @@ void ParserExpectParameter(Instruction* inst) {
|
|||||||
inst->Parameters[0].Type = Register;
|
inst->Parameters[0].Type = Register;
|
||||||
inst->Parameters[0].Value.Register = token->Value.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;
|
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) {
|
if (token->Type == Symbol) {
|
||||||
inst->Parameters[1].Type = Symbol;
|
inst->Parameters[1].Type = Symbol;
|
||||||
inst->Parameters[1].Value.Name = token->Value.String;
|
inst->Parameters[1].Value.Name = token->Value.String;
|
||||||
@@ -148,7 +162,9 @@ void ParserExpectParameter(Instruction* inst) {
|
|||||||
inst->Parameters[1].Type = Register;
|
inst->Parameters[1].Type = Register;
|
||||||
inst->Parameters[1].Value.Register = token->Value.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) {
|
Token* ParserExpect(TokenType type) {
|
||||||
@@ -163,13 +179,60 @@ Token* ParserExpect(TokenType type) {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* ParserWant(TokenType type) {
|
Token* ParserExpectList(int count, ...) {
|
||||||
if (ParserAtEnd()) return NULL;
|
if (ParserAtEnd()) return NULL;
|
||||||
|
|
||||||
Token* token = ParserAdvance();
|
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;
|
if (!token || token->Type != type) return NULL;
|
||||||
|
|
||||||
|
(void) ParserAdvance();
|
||||||
|
|
||||||
return token;
|
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");
|
strcpy(buffer, "FileEnd");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(buffer, 32, "%c", type);
|
snprintf(buffer, 32, "'%c'", type);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user