Files
assm-test/src/parser.c
T

406 lines
10 KiB
C

#include "../includes/parser.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
Token* token;
int address;
} Symbol;
struct intr {
TokenType struction;
unsigned int parameter1;
unsigned int parameter2;
};
Symbol* CreateSymbol(Token* token, int address);
const List* TokensList;
int CurrentToken = 0;
//int HeapStart = 4; // zero indexed, used for declared variables.
//int BinaryEnd = 4; // Zero indexed (binary starts with a 4 byte header)
void AddSymbol(Token*, int);
void PrintSymbols(void);
void HandleOperation(void);
void HandleAssemblerDirective(void);
void AdvanceParser(void);
Token* PeekToken(void);
int ParserAtEnd(void);
int Expect(int, ...);
int ExpectTokenClass(int, ...);
const Symbol* GetSymbol(char*);
List* SymbolsTable;
void WriteMemory(unsigned char value, int location);
void WriteMemoryORMask(unsigned char mask, int location);
unsigned int HeapTop = 4;
unsigned int ProgramCounter = 0;
unsigned char Heap[HIGHMEMORY];
unsigned char Memory[HIGHMEMORY];
unsigned char* ParseTokens(List* tokens) {
if (!tokens) return NULL;
memset(Memory, 0, sizeof(Memory));
memset(Heap, 0, sizeof(Heap));
TokensList = tokens;
SymbolsTable = CreateList();
while(!ParserAtEnd()) {
Token* t = PeekToken();
switch(t->token_class) {
case Directive:
HandleAssemblerDirective();
break;
case Opcode:
HandleOperation();
break;
case Address:
if (t->type == LABEL) {
printf("%s: \n", t->lexeme);
AddSymbol(t, ProgramCounter);
}
break;
default:
break;
}
AdvanceParser();
}
if (SymbolsTable->size > 0) PrintSymbols();
DestroyList(SymbolsTable);
memcpy(&Heap[HeapTop], Memory, ProgramCounter);
int totalSize = HeapTop + ProgramCounter;
Heap[0] = 2 >> HeapTop & 0xFF;
Heap[1] = HeapTop & 0xFF;
Heap[2] = 2 >> totalSize & 0xFF;
Heap[3] = totalSize & 0xFF;
for(int i = 0; i < 33; i++) {
if (i != 0 && i % 3 == 0) printf("\n");
printf("%02X ", Heap[i] & 0xFF);
}
printf("\n");
printf("Program Counter: %d\n", ProgramCounter);
printf("Heap Top: %#06X\n", HeapTop);
return Heap;
}
void HandleAssemblerDirective(void) {
if (PeekToken()->type == DB) {
AdvanceParser();
Token* identifier = PeekToken();
if (!Expect(1, IDENTIFIER)) {
fprintf(stderr, "Expected identifier on line %d\n", identifier->line);
exit(1);
}
AddSymbol(identifier, HeapTop);
identifier = PeekToken();
switch(identifier->type) {
case STRING:
printf("[INFO] %s = '%s' (%#04X)\n", identifier->lexeme, identifier->lexeme, HeapTop);
for(int i = 0; i < strlen(identifier->lexeme); i++) {
//Memory[ProgramCounter + i] = PeekToken()->lexeme[i];
Heap[HeapTop + i] = identifier->lexeme[i];
}
//ProgramCounter += strlen(PeekToken()->lexeme);
HeapTop += strlen(identifier->lexeme);
AdvanceParser();
if (PeekToken()->type == COMMA) {
AdvanceParser();
if (PeekToken()-> type != NUMBER) {
fprintf(stderr, "Expected string termination byte on line %d\n", PeekToken()->line);
exit(1);
}
else {
//Add the NULL byte.
//Memory[ProgramCounter] = '\0';
Heap[HeapTop] = '\0';
//ProgramCounter++;
HeapTop++;
return;
}
}
case NUMBER:
break;
default:
fprintf(stderr, "[Line: %d] Expected either a number or string after identifier '%s'.\n", PeekToken()->line, identifier->lexeme);
exit(1);
}
}
}
void HandleRegisterBasedOpcode(unsigned char instruction, unsigned char mask) {
Memory[ProgramCounter] = mask;
ProgramCounter++;
const Token* token = PeekToken();
if (token->token_class == Reg) {
Memory[ProgramCounter - 1] |= (PeekToken()->type - R1) & 0x07;
AdvanceParser();
}
else {
fprintf(stderr, "[Error] Line %d: Expected register operand.\n", token->line);
exit(1);
}
token = PeekToken();
if (!Expect(1, COMMA)) {
fprintf(stderr, "[Error] Expected command one line %d.\n", token->line);
exit(1);
}
token = PeekToken();
if (token->type == IDENTIFIER || token->type == LABEL) {
const Symbol* symbol = GetSymbol(token->lexeme);
if (!symbol) {
fprintf(stderr, "[Error] Line %d: %s is undefined.\n", token->line, token->lexeme);
exit(1);
}
Memory[ProgramCounter - 1] |= 0x10;//0b00010000;
Memory[ProgramCounter] = 2 >> symbol->address & 0xFF;
Memory[ProgramCounter + 1] = symbol->address & 0xFF;
ProgramCounter += 2;
AdvanceParser();
}
else if (token->type == NUMBER) {
Memory[ProgramCounter - 1] |= 0x08; //0b00001000;
int* value = PeekToken()->value;
Memory[ProgramCounter] = 2 >> *value & 0xFF;
Memory[ProgramCounter + 1] = *value & 0xFF;
ProgramCounter += 2;
AdvanceParser();
} else {
fprintf(stderr, "[Error] Expected operand, got %s\n", token->lexeme);
exit(1);
}
}
void HandleOperation(void) {
const Instruction* inst = GetOpcodeDetails(PeekToken()->type);
const unsigned char registerBasedOpcodeMask = 0xE0;
if (!inst) return;
AdvanceParser();
//Memory[ProgramCounter] = GetInstructionMask(inst->op, inst->parameter_one);
unsigned char mask = GetInstructionMask(inst->op, inst->parameter_one);
if (mask & registerBasedOpcodeMask) {
HandleRegisterBasedOpcode(Memory[ProgramCounter], mask);
return;
}
switch (mask) {
case 0: //NOP
Memory[ProgramCounter] = 0x00;
ProgramCounter++;
return;
case 1: //JZ
Memory[ProgramCounter] = 0x01;
ProgramCounter++;
if (PeekToken()->type == IDENTIFIER || PeekToken()->type == LABEL) {
const Symbol* symbol = GetSymbol(PeekToken()->lexeme);
if (!symbol) {
fprintf(stderr, "[Error] %s is undefined.\n", PeekToken()->lexeme);
exit(1);
}
Memory[ProgramCounter] = 2 >> symbol->address & 0xFF;
Memory[ProgramCounter + 1] = symbol->address & 0xFF;
}
else if (PeekToken()->type == NUMBER) {
int* value = PeekToken()->value;
Memory[ProgramCounter] = 2 >> *value & 0xFF;
Memory[ProgramCounter + 1] = *value & 0xFF;
ProgramCounter += 2;
}
else {
fprintf(stderr, "[Error] Line: %d: Expected address after jump if zero (JZ) instruction.\n", ((Token*) TokensList->content[CurrentToken - 1])->line);
exit(1);
}
ProgramCounter += 2;
return;
case 2: //INT
Memory[ProgramCounter] = 0x02;
ProgramCounter++;
if (PeekToken()->type == NUMBER) {
int* value = PeekToken()->value;
Memory[ProgramCounter] = 2 >> *value & 0xFF;
Memory[ProgramCounter + 1] = *value & 0xFF;
ProgramCounter += 2;
}
else {
fprintf(stderr, "[Error] Line %d: Expected Interrupt vector.\n", PeekToken()->line);
exit(1);
}
return;
}
return;
}
int ExpectTokenClass(int count, ...) {
va_list list;
Token* token = PeekToken();
va_start(list, count);
for(int i = 0; i < count; i++) {
if (va_arg(list, TokenClass) == token->token_class) {
va_end(list);
AdvanceParser();
return 1;
}
}
va_end(list);
return 0;
}
int Expect(int count, ...) {
va_list list;
Token* token = PeekToken();
va_start(list, count);
for(int i = 0; i < count; i++) {
if (va_arg(list, TokenType) == token->type) {
va_end(list);
AdvanceParser();
return 1;
}
}
va_end(list);
return 0;
}
void PrintSymbols(void) {
printf("-----SYMBOLS-----\n");
for(int i = 0; i < SymbolsTable->size; i++) {
Symbol* symbol = SymbolsTable->content[i];
printf("[%#06X] %s\n", symbol->address, symbol->token->lexeme);
}
printf("-----SYMBOLS-----\n");
}
void AddSymbol(Token* token, int address) {
if (!token) return;
if (token->type != IDENTIFIER && token->type != LABEL) return;
for(int i = 0; i < SymbolsTable->size; i++) {
Symbol* s = SymbolsTable->content[i];
if (strcmp(s->token->lexeme, token->lexeme) == 0) return;
}
Symbol* symbol = CreateSymbol(token, address);
AddListItem(symbol, sizeof(Symbol), SymbolsTable);
}
const Symbol* GetSymbol(char* name) {
if (!name) return NULL;
for(int i = 0; i < SymbolsTable->size; i++) {
const Symbol* s = SymbolsTable->content[i];
if (strcmp(s->token->lexeme, name) == 0) return s;
}
return NULL;
}
Symbol* CreateSymbol(Token* token, int address) {
Symbol* symbol = calloc(1, sizeof(Symbol));
if (!symbol) return NULL;
symbol->token = token;
symbol->address = address;
return symbol;
}
void AdvanceParser(void) {
if (ParserAtEnd()) return;
CurrentToken++;
}
int ParserAtEnd(void) {
if (CurrentToken >= TokensList->size) return 1;
return 0;
}
Token* PeekToken(void) {
return TokensList->content[CurrentToken];
}
void WriteMemory(unsigned char value, int location) {
if (location > HIGHMEMORY) {
fprintf(stderr, "[Error] Exceeded memmory size\n");
exit(1);
}
Memory[location] = value;
}
void WriteMemoryORMask(unsigned char mask, int location) {
if (location > HIGHMEMORY) {
fprintf(stderr, "[Error] Exceeded memmory size\n");
exit(1);
}
Memory[location] |= mask;
}