Massive refactoring to simplify this whole setup. The Token List will be modified in place and reused in the Parser to normalize the list and generate a symbols table. Normalizing the token list will make sure the syntax is valid and the symbols table will have the relative offsets and length of symbol values. At least this is all the plan but one step at a time.

This commit is contained in:
2023-03-06 21:51:36 -06:00
parent 1b246e90bc
commit 5e9e1bdec4
7 changed files with 201 additions and 232 deletions
+5 -23
View File
@@ -11,28 +11,11 @@
#define SYMBOLSTABLE_DEFAULT_CAPACITY 128 #define SYMBOLSTABLE_DEFAULT_CAPACITY 128
typedef enum {
StringSymbol,
NumericSymbol,
InstructionPointerSymbol,
UnresolvedSymbol
} SymbolType;
typedef struct {
char* String;
int Terminated;
u_int8_t TerminatingByte;
} SymbolString;
typedef struct { typedef struct {
char* Name; char* Name;
SymbolType Type; int Address;
int Resolved;
union { int Length;
SymbolString* String;
int Number;
Instruction* Instruction;
} Value;
} Symbol; } Symbol;
typedef struct { typedef struct {
@@ -42,9 +25,8 @@ typedef struct {
} SymbolTable; } SymbolTable;
SymbolTable* CreateSymbolTable(void); SymbolTable* CreateSymbolTable(void);
Symbol* TryGetSymbol(char* name, SymbolTable* table); int TryGetSymbol(char* name, SymbolTable* table, Symbol** outSymbol);
Symbol* AddSymbolToTable(char* name, SymbolType type, SymbolTable* table); Symbol* AddSymbolToTable(char* name, int address, int resolved, SymbolTable* table);
SymbolString* CreateSymbolString(char* string, int terminated);
void FreeSymbolTable(SymbolTable* table); void FreeSymbolTable(SymbolTable* table);
void FreeSymbol(Symbol* symbol); void FreeSymbol(Symbol* symbol);
+3 -1
View File
@@ -24,7 +24,9 @@ typedef enum {
typedef enum { typedef enum {
DB, DB,
Include, Include,
Byte Byte,
Load,
Store
} Directive; } Directive;
typedef enum { typedef enum {
+4 -3
View File
@@ -1,4 +1,4 @@
.include "/another_test.asm" .include "./another_test.asm"
.db video_start 0xF37F .db video_start 0xF37F
.db msg "Hello, world!", 0 .db msg "Hello, world!", 0
@@ -13,12 +13,13 @@ load r1, msg ; Because the lod* instructions can't load an address
;Out: Length in R2 ;Out: Length in R2
string_length: string_length:
loadb r3, [r1] ; Load the byte from the address in R1, into R3 load byte r3, [r1] ; Load the byte from the address in R1, into R3
load r2, 0 ; String length load r2, 0 ; String length
cmp r3, null_byte ; Is R3 a null byte? cmp r3, null_byte ; Is R3 a null byte?
je end je end
inc r2 inc r2
start:
inc r1
start: start:
inc r1 ; next char inc r1 ; next char
loadb r3, [r1] ; Load the next character byte into R3 loadb r3, [r1] ; Load the next character byte into R3
+4 -5
View File
@@ -6,6 +6,7 @@
#include "../includes/list.h" #include "../includes/list.h"
#include "../includes/futil.h" #include "../includes/futil.h"
#include "../includes/scanner.h" #include "../includes/scanner.h"
#include "../includes/parser.h"
int main(int argc, char* args[]) { int main(int argc, char* args[]) {
if (argc == 1) { if (argc == 1) {
@@ -31,18 +32,14 @@ int main(int argc, char* args[]) {
if (t->Class == PunctuationClass){ if (t->Class == PunctuationClass){
if(t->Value.Punctuation == NewLine) { if(t->Value.Punctuation == NewLine) {
printf("\n"); printf("<%d>\n", t->LineNumber);
continue; continue;
} }
printf("<%d>", t->LineNumber);
printf(" %c ", t->Value.Punctuation); printf(" %c ", t->Value.Punctuation);
continue; continue;
} }
printf("<%d>", t->LineNumber);
if (t->Class == LabelClass) { if (t->Class == LabelClass) {
printf("[L]%s*", t->Lemexe); printf("[L]%s*", t->Lemexe);
continue; continue;
@@ -79,5 +76,7 @@ int main(int argc, char* args[]) {
} }
} }
ParseTokens(list);
free(source_code); free(source_code);
} }
+168 -180
View File
@@ -14,6 +14,9 @@ Token* PeekToken(void);
int ParserAtEnd(void); int ParserAtEnd(void);
IRState MachineState; IRState MachineState;
int HeapSize = 0;
int PC = 0;
IRState* ParseTokens(List* tokens) { IRState* ParseTokens(List* tokens) {
if (!tokens) return NULL; if (!tokens) return NULL;
@@ -24,49 +27,53 @@ IRState* ParseTokens(List* tokens) {
while(!ParserAtEnd()) { while(!ParserAtEnd()) {
Token* t = PeekToken(); Token* t = PeekToken();
Symbol* tmp;
//printf("Tyoe: %d\n", t->Class);
switch(t->Class) { switch(t->Class) {
case DirectiveClass: //Maybe these should be ignored, let another process handle that. case DirectiveClass: //Maybe these should be ignored, let another process handle that.
HandleAssemblerDirective(); //HandleAssemblerDirective();
break; break;
case MnemonicClass: case MnemonicClass:
HandleOperation(); //HandleOperation();
break; break;
case LabelClass: case LabelClass:
{ {
Symbol* symbol = TryGetSymbol(t->Lemexe, MachineState.SymbolsTable); int found = TryGetSymbol(t->Lemexe, MachineState.SymbolsTable, &tmp);
if (symbol && symbol->Type != UnresolvedSymbol) { if (found && tmp->Resolved) {
fprintf(stderr, "[Error] Line %d: Redefinition of symbol '%s' (type: %d)\n", t->LineNumber, t->Lemexe, symbol->Type); fprintf(stderr, "[Error] Line %d: Redefinition of symbol '%s'\n", t->LineNumber, t->Lemexe);
exit(1); exit(1);
} }
AdvanceParser(); //Consume the label token AdvanceParser(); //Consume the label token
if (!symbol) symbol = AddSymbolToTable(t->Lemexe, InstructionPointerSymbol, MachineState.SymbolsTable); if (!found) AddSymbolToTable(t->Lemexe, HeapSize, 1, MachineState.SymbolsTable);
else symbol->Type = InstructionPointerSymbol; else tmp->Resolved = 1;
AdvanceParser(); //Consume the NewLine AdvanceParser(); //Consume the NewLine
Instruction* ins = HandleOperation(); //Instruction* ins = HandleOperation();
if (!ins) { // if (!ins) {
fprintf(stderr, "[Error] Line %d: Expected instruction following label '%s'.\n", t->LineNumber, t->Lemexe); // fprintf(stderr, "[Error] Line %d: Expected instruction following label '%s'.\n", t->LineNumber, t->Lemexe);
exit(1); // exit(1);
} // }
symbol->Value.Instruction = ins; //symbol->Value.Instruction = ins;
} }
break; break;
default: default:
fprintf(stderr, "[Warning] Line %d: Syntax error, expected start of expression, got '%c' [%d].\n", t->LineNumber, t->Value.Punctuation, t->Class); //fprintf(stderr, "[Warning] Line %d: Syntax error, expected start of expression, got '%c' [%d].\n", t->LineNumber, t->Value.Punctuation, t->Class);
//exit(1); //exit(1);
IgnoreParserLine(); //IgnoreParserLine();
break; break;
} }
AdvanceParser();
} }
if (MachineState.SymbolsTable->Size > 0) PrintSymbols(); PrintSymbols();
return &MachineState; return &MachineState;
} }
@@ -94,12 +101,10 @@ void HandleAssemblerDirective() {
if (token->Class == NumberClass) { if (token->Class == NumberClass) {
//Delcaring a numeric value. //Delcaring a numeric value.
Symbol* s = AddSymbolToTable(symbolname, NumericSymbol, MachineState.SymbolsTable); Symbol* s = AddSymbolToTable(symbolname, HeapSize, 1, MachineState.SymbolsTable);
s->Value.Number = token->Value.Number;
} }
else if (token->Class == CharacterClass) { else if (token->Class == CharacterClass) {
Symbol* s = AddSymbolToTable(symbolname, StringSymbol, MachineState.SymbolsTable); Symbol* s = AddSymbolToTable(symbolname, HeapSize, 1, MachineState.SymbolsTable);
char* string = token->Lemexe; char* string = token->Lemexe;
AdvanceParser(); AdvanceParser();
@@ -119,213 +124,196 @@ void HandleAssemblerDirective() {
exit(1); exit(1);
} }
s->Value.String = CreateSymbolString(string, 1); //s->Value.String = CreateSymbolString(string, 1);
s->Value.String->TerminatingByte = token->Value.Number; //s->Value.String->TerminatingByte = token->Value.Number;
} }
else s->Value.String = CreateSymbolString(string, 0); //else s->Value.String = CreateSymbolString(string, 0);
} }
IgnoreParserLine(); IgnoreParserLine();
} }
Parameter* GetParameterType() { // Parameter* GetParameterType() {
Token* token = PeekToken(); // Token* token = PeekToken();
Symbol* symbol = NULL; // Symbol* symbol = NULL;
Parameter* param = CreateParameter(NoParameter); // int found = 0;
// //Parameter* param = CreateParameter(NoParameter);
switch(token->Class) { // switch(token->Class) {
case RegisterClass: // // case RegisterClass:
param->ParameterType = RegisterParameter; // // param->ParameterType = RegisterParameter;
param->InterpretedAs = RegisterParameter; // // param->InterpretedAs = RegisterParameter;
param->Value.Register = token->Value.Register; // // param->Value.Register = token->Value.Register;
AdvanceParser(); // // AdvanceParser();
return param; // // return param;
//case LabelClass: // //case LabelClass:
case IdentifierClass: // case IdentifierClass:
param->ParameterType = AddressParameter; // found = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable, &symbol);
// if (!found) {
// AddSymbolToTable(token->Lemexe, HeapSize, 0, MachineState.SymbolsTable);
// }
// //param->Value.Symbol = symbol->Name;
// AdvanceParser();
// //return param;
// case PunctuationClass:
// if (token->Value.Punctuation != LBracket) {
// fprintf(stderr, "[Error] Line %d: Expected opening bracket\n", token->LineNumber);
// exit(1);
// }
// AdvanceParser(); // [
// token = PeekToken();
// if (token->Class == NumberClass) {
// param->ParameterType = ConstantParameter;
// param->InterpretedAs = AddressParameter;
// param->Value.Number = token->Value.Number;
// }
// else if (token->Class == RegisterClass) {
// param->ParameterType = RegisterParameter;
// param->InterpretedAs = AddressParameter;
// param->Value.Register = token->Value.Register;
// }
// else if (token->Class & AddressClass) {
// param->ParameterType = AddressParameter;
// param->InterpretedAs = AddressParameter; // param->InterpretedAs = AddressParameter;
symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); // symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable);
if (!symbol) { // if (!symbol) symbol = AddSymbolToTable(token->Lemexe, UnresolvedSymbol, MachineState.SymbolsTable);
symbol = AddSymbolToTable(token->Lemexe, UnresolvedSymbol, MachineState.SymbolsTable);
param->InterpretedAs = UnresolvedParameter;
}
else {
switch(symbol->Type) {
case InstructionPointerSymbol:
case StringSymbol:
param->InterpretedAs = AddressParameter;
break;
case NumericSymbol:
param->InterpretedAs = ConstantParameter;
break;
default:
param->InterpretedAs = UnresolvedParameter;
break;
}
}
param->Value.Symbol = symbol->Name; // param->Value.Symbol = symbol->Name;
// }
// else {
// fprintf(stderr, "[Error] Line %d: Expected identifier, constant number or register.\n", token->LineNumber);
// IgnoreParserLine();
// //return NULL;
// exit(1);
// }
AdvanceParser(); // AdvanceParser(); //Consume the parameter it self.
return param; // token = PeekToken();
case PunctuationClass:
if (token->Value.Punctuation != LBracket) {
fprintf(stderr, "[Error] Line %d: Expected opening bracket\n", token->LineNumber);
exit(1);
}
AdvanceParser(); // [ // if (token->Class != PunctuationClass || token->Value.Punctuation != RBracket) {
// fprintf(stderr, "[Error] Line %d: Expected closing bracket.\n", token->LineNumber);
// exit(1);
// }
token = PeekToken(); // AdvanceParser(); // ]
if (token->Class == NumberClass) { // return param;
param->ParameterType = ConstantParameter; // case NumberClass:
param->InterpretedAs = AddressParameter; // param->ParameterType = ConstantParameter;
param->Value.Number = token->Value.Number; // param->InterpretedAs = ConstantParameter;
}
else if (token->Class == RegisterClass) {
param->ParameterType = RegisterParameter;
param->InterpretedAs = AddressParameter;
param->Value.Register = token->Value.Register;
}
else if (token->Class & AddressClass) {
param->ParameterType = AddressParameter;
param->InterpretedAs = AddressParameter;
symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); // param->Value.Number = token->Value.Number;
if (!symbol) symbol = AddSymbolToTable(token->Lemexe, UnresolvedSymbol, MachineState.SymbolsTable); // AdvanceParser();
param->Value.Symbol = symbol->Name; // return param;
} // default:
else { // break;
fprintf(stderr, "[Error] Line %d: Expected identifier, constant number or register.\n", token->LineNumber); // }
IgnoreParserLine();
// return param;
// }
// Instruction* HandleOperation() {
// if (ParserAtEnd()) {
// //fprintf(stderr, "[Error] Expected instruction mnemonic\n");
// return NULL; // return NULL;
exit(1); // }
}
AdvanceParser(); //Consume the parameter it self. // Token* token = PeekToken();
// //char mn[12];
token = PeekToken(); // if (token->Class != MnemonicClass) {
// fprintf(stderr, "[Error] Line %d: Expected instruction mnemonic\n", token->LineNumber);
// IgnoreParserLine();
// return NULL;
// }
if (token->Class != PunctuationClass || token->Value.Punctuation != RBracket) { // Instruction* ins = CreateInstruction(token->Value.Mnemonic);
fprintf(stderr, "[Error] Line %d: Expected closing bracket.\n", token->LineNumber);
exit(1);
}
AdvanceParser(); // ] // //GetMnemonicText(ins->Mnemonic, mn);
return param; // AdvanceParser();
case NumberClass:
param->ParameterType = ConstantParameter;
param->InterpretedAs = ConstantParameter;
param->Value.Number = token->Value.Number; // //No parameters here, we have a line break.
// if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) {
// goto InsertInstruction;
// }
AdvanceParser(); // ins->ParameterOne = GetParameterType();
return param; // if (ins->ParameterOne->ParameterType == NoParameter) {
default: // //This would be an error if the next token isn't a line break.
break; // if (PeekToken()->Class != PunctuationClass || PeekToken()->Value.Punctuation != NewLine) {
} // fprintf(stderr, "[Error] Line %d: Syntax error, expected line break but got %s.\n", token->LineNumber, token->Lemexe);
// exit(1);
// }
return param; // goto InsertInstruction;
} // }
Instruction* HandleOperation() { // if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) {
if (ParserAtEnd()) { // goto InsertInstruction;
//fprintf(stderr, "[Error] Expected instruction mnemonic\n"); // }
return NULL;
}
Token* token = PeekToken(); // if (PeekToken()->Class != PunctuationClass || PeekToken()->Value.Punctuation != Comma) {
//char mn[12]; // //Syntax error
// fprintf(stderr, "[Error] Line %d: Expected comma got %d.\n", token->LineNumber, token->Class);
// exit(1);
// }
if (token->Class != MnemonicClass) { // AdvanceParser(); //Consume the comma
fprintf(stderr, "[Error] Line %d: Expected instruction mnemonic\n", token->LineNumber);
IgnoreParserLine();
return NULL;
}
Instruction* ins = CreateInstruction(token->Value.Mnemonic); // ins->ParameterTwo = GetParameterType();
//GetMnemonicText(ins->Mnemonic, mn); // InsertInstruction:
AdvanceParser(); // AddListItem(ins, MachineState.Instructions);
//No parameters here, we have a line break. // AdvanceParser(); //Consume the line break
if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) {
goto InsertInstruction;
}
ins->ParameterOne = GetParameterType(); // return ins;
// }
if (ins->ParameterOne->ParameterType == NoParameter) {
//This would be an error if the next token isn't a line break.
if (PeekToken()->Class != PunctuationClass || PeekToken()->Value.Punctuation != NewLine) {
fprintf(stderr, "[Error] Line %d: Syntax error, expected line break but got %s.\n", token->LineNumber, token->Lemexe);
exit(1);
}
goto InsertInstruction;
}
if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) {
goto InsertInstruction;
}
if (PeekToken()->Class != PunctuationClass || PeekToken()->Value.Punctuation != Comma) {
//Syntax error
fprintf(stderr, "[Error] Line %d: Expected comma got %d.\n", token->LineNumber, token->Class);
exit(1);
}
AdvanceParser(); //Consume the comma
ins->ParameterTwo = GetParameterType();
InsertInstruction:
AddListItem(ins, MachineState.Instructions);
AdvanceParser(); //Consume the line break
return ins;
}
void PrintSymbols(void) { void PrintSymbols(void) {
char mn[12]; //char mn[12];
printf("-----SYMBOLS-----\n"); printf("-----SYMBOLS-----\n");
for(int i = 0; i < MachineState.SymbolsTable->Size; i++) { for(int i = 0; i < MachineState.SymbolsTable->Size; i++) {
Symbol* symbol = MachineState.SymbolsTable->Symbols[i]; Symbol* symbol = MachineState.SymbolsTable->Symbols[i];
printf("[%s] ", symbol->Type == UnresolvedSymbol ? "Unresolved" : "Resolved"); printf("[%s] %s", symbol->Resolved == 0 ? "Unresolved" : "Resolved", symbol->Name);
switch(symbol->Type) { // switch(symbol->Type) {
case InstructionPointerSymbol: // case InstructionPointerSymbol:
GetMnemonicText(symbol->Value.Instruction->Mnemonic, mn); // GetMnemonicText(symbol->Value.Instruction->Mnemonic, mn);
printf("%s -> %s", symbol->Name, mn); // printf("%s -> %s", symbol->Name, mn);
break; // break;
case NumericSymbol: // case NumericSymbol:
printf("[N] %s Value: %d", symbol->Name, symbol->Value.Number); // printf("[N] %s Value: %d", symbol->Name, symbol->Value.Number);
break; // break;
case StringSymbol: // case StringSymbol:
if (symbol->Value.String->Terminated) // if (symbol->Value.String->Terminated)
printf("[S] %s {%s}, %d", symbol->Name, symbol->Value.String->String, symbol->Value.String->TerminatingByte); // printf("[S] %s {%s}, %d", symbol->Name, symbol->Value.String->String, symbol->Value.String->TerminatingByte);
else // else
printf("[S] %s {%s}", symbol->Name, symbol->Value.String->String); // printf("[S] %s {%s}", symbol->Name, symbol->Value.String->String);
break; // break;
case UnresolvedSymbol: // case UnresolvedSymbol:
printf("[U] %s", symbol->Name); // printf("[U] %s", symbol->Name);
break; // break;
} // }
printf("\n"); printf("\n");
} }
+8
View File
@@ -283,6 +283,14 @@ Token* ParseIdentifier(void) {
return token; return token;
} }
if (strcmp(lexeme, "load") == 0) {
Token* token = CreateToken(Line, DirectiveClass);
token->Lemexe = lexeme;
token->Value.Directive = Load;
return token;
}
Token* token = CreateToken(Line, IdentifierClass); Token* token = CreateToken(Line, IdentifierClass);
+14 -25
View File
@@ -25,7 +25,7 @@ SymbolTable* CreateSymbolTable(void){
return table; return table;
} }
Symbol* CreateSymbol(char* name, SymbolType type) { Symbol* CreateSymbol(char* name, int address, int resolved) {
Symbol* symbol = calloc(1, sizeof(Symbol)); Symbol* symbol = calloc(1, sizeof(Symbol));
if (!symbol) { if (!symbol) {
@@ -34,40 +34,29 @@ Symbol* CreateSymbol(char* name, SymbolType type) {
return NULL; return NULL;
} }
symbol->Type = type; symbol->Address = address;
symbol->Name = name; symbol->Name = name;
symbol->Resolved = resolved;
return symbol; return symbol;
} }
SymbolString* CreateSymbolString(char* string, int terminated) { int TryGetSymbol(char* name, SymbolTable* table, Symbol** outSymbol) {
if (!string) return NULL; *outSymbol = NULL;
SymbolString* s = calloc(1, sizeof(SymbolString)); if (!name || !table) return 0;
if (!s) {
fprintf(stderr, "Failed to calloc string for symbol. %s.\n", strerror(errno));
return NULL;
}
s->String = string;
s->Terminated = terminated;
return s;
}
Symbol* TryGetSymbol(char* name, SymbolTable* table) {
if (!name || !table) return NULL;
for(int i = 0; i < table->Size; i++) { for(int i = 0; i < table->Size; i++) {
if (strcmp(table->Symbols[i]->Name, name) == 0) return table->Symbols[i]; if (strcmp(table->Symbols[i]->Name, name) == 0) {
*outSymbol = table->Symbols[i];
return 1;
}
} }
return NULL; return 0;
} }
Symbol* AddSymbolToTable(char* name, SymbolType type, SymbolTable* table) { Symbol* AddSymbolToTable(char* name, int address, int resolved, SymbolTable* table) {
//if (!name || !value || !table || length == 0) return NULL; //if (!name || !value || !table || length == 0) return NULL;
for(int i = 0; i < table->Size; i++) { for(int i = 0; i < table->Size; i++) {
@@ -79,7 +68,7 @@ Symbol* AddSymbolToTable(char* name, SymbolType type, SymbolTable* table) {
} }
if (table->Capacity < table->Size + 1) { if (table->Capacity < table->Size + 1) {
Symbol** newBlock = realloc(table->Symbols, sizeof(Symbol*) * table->Capacity * 2);//calloc(table->Size * 2, sizeof(Symbol*)); Symbol** newBlock = realloc(table->Symbols, sizeof(Symbol*) * table->Capacity * 2);
if (!newBlock) { if (!newBlock) {
fprintf(stderr, "Failed to realloc space for a new symbol '%s'. %s.\n", name, strerror(errno)); fprintf(stderr, "Failed to realloc space for a new symbol '%s'. %s.\n", name, strerror(errno));
@@ -91,7 +80,7 @@ Symbol* AddSymbolToTable(char* name, SymbolType type, SymbolTable* table) {
table->Symbols = newBlock; table->Symbols = newBlock;
} }
Symbol* symbol = CreateSymbol(name, type); Symbol* symbol = CreateSymbol(name, address, resolved);
table->Symbols[table->Size] = symbol; table->Symbols[table->Size] = symbol;
table->Size++; table->Size++;