300 lines
7.3 KiB
C
300 lines
7.3 KiB
C
#include "../includes/parser.h"
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifndef HIGHMEMORY
|
|
#define HIGHMEMORY 65535 //64KiB - 1 AKA 0xFFFF
|
|
#endif
|
|
|
|
//#define HEAPTOP HIGHMEMORY
|
|
|
|
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 HeapTop = HIGHMEMORY;
|
|
|
|
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;
|
|
unsigned int ProgramCounter = 0;
|
|
|
|
void ParseTokens(List* tokens) {
|
|
if (!tokens) return;
|
|
|
|
TokensList = tokens;
|
|
|
|
SymbolsTable = CreateList();
|
|
|
|
while(!ParserAtEnd()) {
|
|
Token* t = PeekToken();
|
|
|
|
switch(t->token_class) {
|
|
case Directive:
|
|
HandleAssemblerDirective();
|
|
break;
|
|
case Opcode:
|
|
ProgramCounter++;
|
|
HandleOperation();
|
|
break;
|
|
case Immediate16:
|
|
ProgramCounter++;
|
|
AddSymbol(t, ProgramCounter);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
AdvanceParser();
|
|
}
|
|
|
|
PrintSymbols();
|
|
DestroyList(SymbolsTable);
|
|
printf("Program Counter: %d\n", ProgramCounter);
|
|
//printf("Heap Top: %#06X\n", HeapTop);
|
|
}
|
|
|
|
void HandleAssemblerDirective(void) {
|
|
|
|
if (PeekToken()->type == DB) {
|
|
AdvanceParser();
|
|
|
|
Token* identifier = PeekToken();
|
|
|
|
if (!Expect(1, IDENTIFIER)) {
|
|
fprintf(stderr, "Expected identifier on line %d\n", PeekToken()->line);
|
|
exit(1);
|
|
}
|
|
|
|
AddSymbol(identifier, ProgramCounter);
|
|
|
|
switch(PeekToken()->type) {
|
|
case STRING:
|
|
ProgramCounter += strlen(PeekToken()->lexeme);
|
|
|
|
printf("[INFO] %s = '%s'\n", identifier->lexeme, PeekToken()->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.
|
|
ProgramCounter++;
|
|
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 HandleOperation(void) {
|
|
const Instruction* inst = GetOpcodeDetails(PeekToken()->type);
|
|
|
|
if (!inst) return;
|
|
|
|
AdvanceParser();
|
|
|
|
printf("[%#05X] %s ", ProgramCounter, inst->lexeme);
|
|
|
|
if (inst->parameter_one == None) {
|
|
printf("\n");
|
|
return;
|
|
}
|
|
|
|
if (inst->parameter_one && PeekToken()->token_class > 0) {
|
|
//printf("Matched '%s'\n", PeekToken()->lexeme);
|
|
|
|
if (inst->parameter_one & Reg) {
|
|
//Encode the register number here.
|
|
printf("%s ", PeekToken()->lexeme);
|
|
}
|
|
else if (inst->parameter_one & Immediate16) {
|
|
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);
|
|
}
|
|
|
|
printf("[%s@%#04X] ", PeekToken()->lexeme, symbol->address);
|
|
}
|
|
else if (PeekToken()->type == NUMBER) printf("%s ", PeekToken()->lexeme);
|
|
|
|
ProgramCounter += 2;
|
|
}
|
|
|
|
AdvanceParser();
|
|
}
|
|
|
|
if (inst->parameter_two == None) {
|
|
printf("\n");
|
|
return;
|
|
}
|
|
|
|
if (PeekToken()->type == COMMA) {
|
|
AdvanceParser();
|
|
} else {
|
|
fprintf(stderr, "Expected comma at line %d\n", PeekToken()->line);
|
|
exit(666);
|
|
return;
|
|
}
|
|
|
|
if (inst->parameter_two && PeekToken()->token_class > 0) {
|
|
//printf("Matched 2 '%s'\n", PeekToken()->lexeme);
|
|
if (inst->parameter_two & Immediate16) {
|
|
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);
|
|
}
|
|
|
|
printf("[%s@%#04X] ", PeekToken()->lexeme, symbol->address);
|
|
}
|
|
else if (PeekToken()->type == NUMBER) printf("%s ", PeekToken()->lexeme);
|
|
|
|
ProgramCounter += 2;
|
|
}
|
|
|
|
AdvanceParser();
|
|
} else {
|
|
printf("Failed to match %s (class: %d)\n", PeekToken()->lexeme, PeekToken()->token_class);
|
|
printf("Inst %s (class: %x)\n", inst->lexeme, inst->parameter_two);
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
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];
|
|
} |