Reworked the tokens to include a broad class to make parameter matching a bit easier, and removed the hexadecimal distinction.
This commit is contained in:
+5
-11
@@ -7,29 +7,23 @@
|
|||||||
#define OPCODECOUNT 10
|
#define OPCODECOUNT 10
|
||||||
#define REGISTERCOUNT 8
|
#define REGISTERCOUNT 8
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
None = 0,
|
|
||||||
Reg,
|
|
||||||
Imm8,
|
|
||||||
Imm16
|
|
||||||
} ParameterType;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* lexeme;
|
char* lexeme;
|
||||||
TokenType op;
|
TokenType op;
|
||||||
ParameterType parameter_one;
|
TokenClass parameter_one;
|
||||||
ParameterType parameter_two;
|
TokenClass parameter_two;
|
||||||
} OpCode;
|
} Instruction;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* lexeme;
|
char* lexeme;
|
||||||
TokenType type;
|
TokenType type;
|
||||||
} Register;
|
} Register;
|
||||||
|
|
||||||
extern OpCode opcodes[OPCODECOUNT];
|
extern Instruction instructions[OPCODECOUNT];
|
||||||
extern Register registers[REGISTERCOUNT];
|
extern Register registers[REGISTERCOUNT];
|
||||||
|
|
||||||
int IsOpcode(const char*, TokenType*);
|
int IsOpcode(const char*, TokenType*);
|
||||||
int IsRegister(const char*, TokenType*);
|
int IsRegister(const char*, TokenType*);
|
||||||
|
const Instruction* GetOpcodeDetails(TokenType);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+8
-1
@@ -21,7 +21,6 @@ typedef enum {
|
|||||||
IDENTIFIER,
|
IDENTIFIER,
|
||||||
LABEL,
|
LABEL,
|
||||||
NUMBER,
|
NUMBER,
|
||||||
HEX,
|
|
||||||
//Keywords
|
//Keywords
|
||||||
DB, ORG,
|
DB, ORG,
|
||||||
//Opcodes
|
//Opcodes
|
||||||
@@ -31,11 +30,19 @@ typedef enum {
|
|||||||
R1, R2, R3, R4, R5, R6, R7, R8
|
R1, R2, R3, R4, R5, R6, R7, R8
|
||||||
} TokenType;
|
} TokenType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
None,
|
||||||
|
Reg,
|
||||||
|
Immediate16,
|
||||||
|
Opcode
|
||||||
|
} TokenClass;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
TokenType type;
|
TokenType type;
|
||||||
char* lexeme;
|
char* lexeme;
|
||||||
void* value;
|
void* value;
|
||||||
int line;
|
int line;
|
||||||
|
TokenClass token_class;
|
||||||
} Token;
|
} Token;
|
||||||
|
|
||||||
Token* CreateToken(char*, void*, int, TokenType);
|
Token* CreateToken(char*, void*, int, TokenType);
|
||||||
|
|||||||
+17
-9
@@ -2,15 +2,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
OpCode opcodes[OPCODECOUNT] = {
|
Instruction instructions[OPCODECOUNT] = {
|
||||||
{ "copy", COPY, Reg, Reg | Imm8 | Imm16 },
|
{ "copy", COPY, Reg, Reg | Immediate16 },
|
||||||
{ "add", ADD, Reg, Reg | Imm8 | Imm16 },
|
{ "add", ADD, Reg, Reg | Immediate16 },
|
||||||
{ "sub", SUB, Reg, Reg | Imm8 | Imm16 },
|
{ "sub", SUB, Reg, Reg | Immediate16 },
|
||||||
{ "jz", JZ, Imm8 | Imm16, None },
|
{ "jz", JZ, Immediate16, None },
|
||||||
{ "int", INT, Imm8, None },
|
{ "int", INT, Immediate16, None },
|
||||||
{ "yld", YLD, None, None },
|
{ "yld", YLD, None, None },
|
||||||
{ "ret", RET, None, None },
|
{ "ret", RET, None, None },
|
||||||
{ "cmp", CMP, Reg | Imm8 | Imm16, Reg | Imm8 | Imm16 },
|
{ "cmp", CMP, Reg | Immediate16, Reg | Immediate16 },
|
||||||
{ "in", IN, None, None},
|
{ "in", IN, None, None},
|
||||||
{ "out", OUT, None, None}
|
{ "out", OUT, None, None}
|
||||||
};
|
};
|
||||||
@@ -26,12 +26,20 @@ Register registers[REGISTERCOUNT] = {
|
|||||||
{ "r8", R8 }
|
{ "r8", R8 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Instruction* GetOpcodeDetails(TokenType type) {
|
||||||
|
for(int i = 0; i < OPCODECOUNT; i++) {
|
||||||
|
if (instructions[i].op == type) return &instructions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int IsOpcode(const char* text, TokenType* opcode) {
|
int IsOpcode(const char* text, TokenType* opcode) {
|
||||||
if (!text) return 0;
|
if (!text) return 0;
|
||||||
|
|
||||||
for(int i = 0; i < OPCODECOUNT; i++) {
|
for(int i = 0; i < OPCODECOUNT; i++) {
|
||||||
if (strcmp(opcodes[i].lexeme, text) == 0) {
|
if (strcmp(instructions[i].lexeme, text) == 0) {
|
||||||
if (opcode) *opcode = opcodes[i].op;
|
if (opcode) *opcode = instructions[i].op;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-6
@@ -1,4 +1,5 @@
|
|||||||
#include "../includes/parser.h"
|
#include "../includes/parser.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifndef HIGHMEMORY
|
#ifndef HIGHMEMORY
|
||||||
#define HIGHMEMORY 65535 //64KiB - 1 AKA 0xFFFF
|
#define HIGHMEMORY 65535 //64KiB - 1 AKA 0xFFFF
|
||||||
@@ -10,13 +11,24 @@ typedef struct {
|
|||||||
} Symbol;
|
} Symbol;
|
||||||
|
|
||||||
Symbol* CreateSymbol(Token*, int);
|
Symbol* CreateSymbol(Token*, int);
|
||||||
|
const List* TokensList;
|
||||||
|
int CurrentToken = 0;
|
||||||
|
|
||||||
void AddSymbol(Token*, int);
|
void AddSymbol(Token*, int);
|
||||||
void PrintSymbols(void);
|
void PrintSymbols(void);
|
||||||
|
void HandleOperation(Token*);
|
||||||
|
void AdvanceParser(void);
|
||||||
|
Token* PeekToken(void);
|
||||||
|
int Expect(int, ...);
|
||||||
Token* GetSymbol(char*);
|
Token* GetSymbol(char*);
|
||||||
List* SymbolsTable;
|
List* SymbolsTable;
|
||||||
unsigned int ProgramCounter = 0;
|
unsigned int ProgramCounter = 0;
|
||||||
|
|
||||||
void ParseTokens(List* tokens) {
|
void ParseTokens(List* tokens) {
|
||||||
|
if (!tokens) return;
|
||||||
|
|
||||||
|
TokensList = tokens;
|
||||||
|
|
||||||
SymbolsTable = CreateList();
|
SymbolsTable = CreateList();
|
||||||
|
|
||||||
for(int i = 0; i < tokens->size; i++){
|
for(int i = 0; i < tokens->size; i++){
|
||||||
@@ -30,12 +42,13 @@ void ParseTokens(List* tokens) {
|
|||||||
case STRING:
|
case STRING:
|
||||||
ProgramCounter += strlen(t->lexeme);
|
ProgramCounter += strlen(t->lexeme);
|
||||||
break;
|
break;
|
||||||
case NUMBER:
|
case NUMBER: //Number's will be 2 bytes
|
||||||
case HEX: //Number's will be 2 bytes
|
|
||||||
ProgramCounter += 2;
|
ProgramCounter += 2;
|
||||||
break;
|
break;
|
||||||
default: //Instructions are 1 byte wide.
|
default: //Instructions are 1 byte wide.
|
||||||
if (IsOpcode(t->lexeme, NULL)) ProgramCounter += 1;
|
if (t->token_class == Opcode) {
|
||||||
|
ProgramCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -46,6 +59,32 @@ void ParseTokens(List* tokens) {
|
|||||||
printf("Program Counter: %d\n", ProgramCounter);
|
printf("Program Counter: %d\n", ProgramCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HandleOperation(Token* token) {
|
||||||
|
const Instruction* inst = GetOpcodeDetails(token->type);
|
||||||
|
|
||||||
|
if (!inst) return;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int Expect(int count, ...) {
|
||||||
|
va_list list;
|
||||||
|
|
||||||
|
va_start(list, count);
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
if (va_arg(list, TokenClass) == PeekToken()->token_class) {
|
||||||
|
va_end(list);
|
||||||
|
//advance
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PrintSymbols(void) {
|
void PrintSymbols(void) {
|
||||||
printf("-----SYMBOLS-----\n");
|
printf("-----SYMBOLS-----\n");
|
||||||
for(int i = 0; i < SymbolsTable->size; i++) {
|
for(int i = 0; i < SymbolsTable->size; i++) {
|
||||||
@@ -79,9 +118,7 @@ Token* GetSymbol(char* name) {
|
|||||||
Symbol* CreateSymbol(Token* token, int address) {
|
Symbol* CreateSymbol(Token* token, int address) {
|
||||||
Symbol* symbol = calloc(1, sizeof(Symbol));
|
Symbol* symbol = calloc(1, sizeof(Symbol));
|
||||||
|
|
||||||
if (!symbol) {
|
if (!symbol) return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
symbol->token = token;
|
symbol->token = token;
|
||||||
symbol->address = address;
|
symbol->address = address;
|
||||||
|
|||||||
+3
-7
@@ -79,13 +79,11 @@ List* GenerateTokenList(const char* source) {
|
|||||||
|
|
||||||
Token* ParseNumber(void) {
|
Token* ParseNumber(void) {
|
||||||
int start = Position;
|
int start = Position;
|
||||||
int base = 10;
|
|
||||||
|
|
||||||
while(!ScannerAtEnd() && isdigit(PeekScanner()))
|
while(!ScannerAtEnd() && isdigit(PeekScanner()))
|
||||||
AdvanceScanner();
|
AdvanceScanner();
|
||||||
|
|
||||||
if (PeekScanner() == 'x' && isdigit(PeekAheadScanner())) {
|
if (PeekScanner() == 'x' && isdigit(PeekAheadScanner())) {
|
||||||
base = 16;
|
|
||||||
AdvanceScanner(); //Consume the 'x'
|
AdvanceScanner(); //Consume the 'x'
|
||||||
while(!ScannerAtEnd() && isdigit(PeekScanner())) AdvanceScanner();
|
while(!ScannerAtEnd() && isdigit(PeekScanner())) AdvanceScanner();
|
||||||
}
|
}
|
||||||
@@ -109,12 +107,10 @@ Token* ParseNumber(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(lexeme, &SourceCode[start], length);
|
memcpy(lexeme, &SourceCode[start], length);
|
||||||
|
// Setting the base to zero means the function will pick the base.
|
||||||
|
*value = strtol(lexeme, NULL, 0);
|
||||||
|
|
||||||
*value = strtol(lexeme, NULL, base);
|
return CreateToken(lexeme, value, Line, NUMBER);
|
||||||
|
|
||||||
if (base == 10) return CreateToken(lexeme, value, Line, NUMBER);
|
|
||||||
|
|
||||||
return CreateToken(lexeme, value, Line, HEX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* ParseDirective(void) {
|
Token* ParseDirective(void) {
|
||||||
|
|||||||
+18
@@ -1,5 +1,7 @@
|
|||||||
#include "../includes/token.h"
|
#include "../includes/token.h"
|
||||||
|
|
||||||
|
TokenClass GetTokenClass(TokenType);
|
||||||
|
|
||||||
Token* CreateToken(char* lexeme, void* value, int lineNumber, TokenType type) {
|
Token* CreateToken(char* lexeme, void* value, int lineNumber, TokenType type) {
|
||||||
Token* token = calloc(1, sizeof(Token));
|
Token* token = calloc(1, sizeof(Token));
|
||||||
|
|
||||||
@@ -12,10 +14,26 @@ Token* CreateToken(char* lexeme, void* value, int lineNumber, TokenType type) {
|
|||||||
token->line = lineNumber;
|
token->line = lineNumber;
|
||||||
token->lexeme = lexeme;
|
token->lexeme = lexeme;
|
||||||
token->value = value;
|
token->value = value;
|
||||||
|
token->token_class = GetTokenClass(type);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TokenClass GetTokenClass(TokenType type) {
|
||||||
|
if (type >= R1 && type <= R8) return Reg;
|
||||||
|
if (type >= COPY && type <= OUT) return Opcode;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case STRING:
|
||||||
|
case IDENTIFIER:
|
||||||
|
case LABEL:
|
||||||
|
case NUMBER:
|
||||||
|
return Immediate16;
|
||||||
|
default:
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FreeToken(Token* token) {
|
void FreeToken(Token* token) {
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user