From 5e9e1bdec480f35fe72320e27d85297a155e6a84 Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Mon, 6 Mar 2023 21:51:36 -0600 Subject: [PATCH] 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. --- includes/symbols_table.h | 28 +--- includes/token.h | 4 +- misc/test.asm | 7 +- src/main.c | 13 +- src/parser.c | 334 +++++++++++++++++++-------------------- src/scanner.c | 8 + src/symbols_table.c | 39 ++--- 7 files changed, 201 insertions(+), 232 deletions(-) diff --git a/includes/symbols_table.h b/includes/symbols_table.h index 5c55735..4e74cc7 100644 --- a/includes/symbols_table.h +++ b/includes/symbols_table.h @@ -11,28 +11,11 @@ #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 { char* Name; - SymbolType Type; - - union { - SymbolString* String; - int Number; - Instruction* Instruction; - } Value; + int Address; + int Resolved; + int Length; } Symbol; typedef struct { @@ -42,9 +25,8 @@ typedef struct { } SymbolTable; SymbolTable* CreateSymbolTable(void); -Symbol* TryGetSymbol(char* name, SymbolTable* table); -Symbol* AddSymbolToTable(char* name, SymbolType type, SymbolTable* table); -SymbolString* CreateSymbolString(char* string, int terminated); +int TryGetSymbol(char* name, SymbolTable* table, Symbol** outSymbol); +Symbol* AddSymbolToTable(char* name, int address, int resolved, SymbolTable* table); void FreeSymbolTable(SymbolTable* table); void FreeSymbol(Symbol* symbol); diff --git a/includes/token.h b/includes/token.h index a26acdd..cf3f5e2 100644 --- a/includes/token.h +++ b/includes/token.h @@ -24,7 +24,9 @@ typedef enum { typedef enum { DB, Include, - Byte + Byte, + Load, + Store } Directive; typedef enum { diff --git a/misc/test.asm b/misc/test.asm index 7bc3d3a..3ffc897 100644 --- a/misc/test.asm +++ b/misc/test.asm @@ -1,4 +1,4 @@ -.include "/another_test.asm" +.include "./another_test.asm" .db video_start 0xF37F .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 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 cmp r3, null_byte ; Is R3 a null byte? je end inc r2 - +start: + inc r1 start: inc r1 ; next char loadb r3, [r1] ; Load the next character byte into R3 diff --git a/src/main.c b/src/main.c index 0753371..ab85657 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,7 @@ #include "../includes/list.h" #include "../includes/futil.h" #include "../includes/scanner.h" +#include "../includes/parser.h" int main(int argc, char* args[]) { if (argc == 1) { @@ -31,20 +32,16 @@ int main(int argc, char* args[]) { if (t->Class == PunctuationClass){ if(t->Value.Punctuation == NewLine) { - printf("\n"); + printf("<%d>\n", t->LineNumber); continue; } - printf("<%d>", t->LineNumber); - - printf("%c ", t->Value.Punctuation); + printf(" %c ", t->Value.Punctuation); continue; } - printf("<%d>", t->LineNumber); - if (t->Class == LabelClass) { - printf("[L]%s* ", t->Lemexe); + printf("[L]%s*", t->Lemexe); continue; } @@ -79,5 +76,7 @@ int main(int argc, char* args[]) { } } + ParseTokens(list); + free(source_code); } \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index a83e615..703c0e1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -14,6 +14,9 @@ Token* PeekToken(void); int ParserAtEnd(void); IRState MachineState; +int HeapSize = 0; +int PC = 0; + IRState* ParseTokens(List* tokens) { if (!tokens) return NULL; @@ -24,49 +27,53 @@ IRState* ParseTokens(List* tokens) { while(!ParserAtEnd()) { Token* t = PeekToken(); + Symbol* tmp; + //printf("Tyoe: %d\n", t->Class); switch(t->Class) { case DirectiveClass: //Maybe these should be ignored, let another process handle that. - HandleAssemblerDirective(); + //HandleAssemblerDirective(); break; case MnemonicClass: - HandleOperation(); + //HandleOperation(); break; case LabelClass: { - Symbol* symbol = TryGetSymbol(t->Lemexe, MachineState.SymbolsTable); + int found = TryGetSymbol(t->Lemexe, MachineState.SymbolsTable, &tmp); - if (symbol && symbol->Type != UnresolvedSymbol) { - fprintf(stderr, "[Error] Line %d: Redefinition of symbol '%s' (type: %d)\n", t->LineNumber, t->Lemexe, symbol->Type); + if (found && tmp->Resolved) { + fprintf(stderr, "[Error] Line %d: Redefinition of symbol '%s'\n", t->LineNumber, t->Lemexe); exit(1); } AdvanceParser(); //Consume the label token - if (!symbol) symbol = AddSymbolToTable(t->Lemexe, InstructionPointerSymbol, MachineState.SymbolsTable); - else symbol->Type = InstructionPointerSymbol; + if (!found) AddSymbolToTable(t->Lemexe, HeapSize, 1, MachineState.SymbolsTable); + else tmp->Resolved = 1; AdvanceParser(); //Consume the NewLine - Instruction* ins = HandleOperation(); + //Instruction* ins = HandleOperation(); - if (!ins) { - fprintf(stderr, "[Error] Line %d: Expected instruction following label '%s'.\n", t->LineNumber, t->Lemexe); - exit(1); - } + // if (!ins) { + // fprintf(stderr, "[Error] Line %d: Expected instruction following label '%s'.\n", t->LineNumber, t->Lemexe); + // exit(1); + // } - symbol->Value.Instruction = ins; + //symbol->Value.Instruction = ins; } break; 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); - IgnoreParserLine(); + //IgnoreParserLine(); break; } + + AdvanceParser(); } - if (MachineState.SymbolsTable->Size > 0) PrintSymbols(); + PrintSymbols(); return &MachineState; } @@ -94,12 +101,10 @@ void HandleAssemblerDirective() { if (token->Class == NumberClass) { //Delcaring a numeric value. - Symbol* s = AddSymbolToTable(symbolname, NumericSymbol, MachineState.SymbolsTable); - - s->Value.Number = token->Value.Number; + Symbol* s = AddSymbolToTable(symbolname, HeapSize, 1, MachineState.SymbolsTable); } else if (token->Class == CharacterClass) { - Symbol* s = AddSymbolToTable(symbolname, StringSymbol, MachineState.SymbolsTable); + Symbol* s = AddSymbolToTable(symbolname, HeapSize, 1, MachineState.SymbolsTable); char* string = token->Lemexe; AdvanceParser(); @@ -119,213 +124,196 @@ void HandleAssemblerDirective() { exit(1); } - s->Value.String = CreateSymbolString(string, 1); - s->Value.String->TerminatingByte = token->Value.Number; + //s->Value.String = CreateSymbolString(string, 1); + //s->Value.String->TerminatingByte = token->Value.Number; } - else s->Value.String = CreateSymbolString(string, 0); + //else s->Value.String = CreateSymbolString(string, 0); } IgnoreParserLine(); } -Parameter* GetParameterType() { - Token* token = PeekToken(); - Symbol* symbol = NULL; - Parameter* param = CreateParameter(NoParameter); +// Parameter* GetParameterType() { +// Token* token = PeekToken(); +// Symbol* symbol = NULL; +// int found = 0; +// //Parameter* param = CreateParameter(NoParameter); - switch(token->Class) { - case RegisterClass: - param->ParameterType = RegisterParameter; - param->InterpretedAs = RegisterParameter; +// switch(token->Class) { +// // case RegisterClass: +// // param->ParameterType = RegisterParameter; +// // param->InterpretedAs = RegisterParameter; - param->Value.Register = token->Value.Register; +// // param->Value.Register = token->Value.Register; - AdvanceParser(); +// // AdvanceParser(); - return param; - //case LabelClass: - case IdentifierClass: - param->ParameterType = AddressParameter; - //param->InterpretedAs = AddressParameter; +// // return param; +// //case LabelClass: +// case IdentifierClass: +// found = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable, &symbol); - symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); +// if (!found) { +// AddSymbolToTable(token->Lemexe, HeapSize, 0, MachineState.SymbolsTable); +// } - if (!symbol) { - 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; +// AdvanceParser(); - AdvanceParser(); +// //return param; +// case PunctuationClass: +// if (token->Value.Punctuation != LBracket) { +// fprintf(stderr, "[Error] Line %d: Expected opening bracket\n", token->LineNumber); +// exit(1); +// } - return param; - case PunctuationClass: - if (token->Value.Punctuation != LBracket) { - fprintf(stderr, "[Error] Line %d: Expected opening bracket\n", token->LineNumber); - exit(1); - } +// AdvanceParser(); // [ - AdvanceParser(); // [ +// token = PeekToken(); - 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; - 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; +// symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); - symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); +// if (!symbol) symbol = AddSymbolToTable(token->Lemexe, UnresolvedSymbol, MachineState.SymbolsTable); - if (!symbol) symbol = AddSymbolToTable(token->Lemexe, UnresolvedSymbol, MachineState.SymbolsTable); +// 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); +// } - 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(); //Consume the parameter it self. - AdvanceParser(); //Consume the parameter it self. +// token = PeekToken(); - token = PeekToken(); +// if (token->Class != PunctuationClass || token->Value.Punctuation != RBracket) { +// fprintf(stderr, "[Error] Line %d: Expected closing bracket.\n", token->LineNumber); +// exit(1); +// } - if (token->Class != PunctuationClass || token->Value.Punctuation != RBracket) { - fprintf(stderr, "[Error] Line %d: Expected closing bracket.\n", token->LineNumber); - exit(1); - } +// AdvanceParser(); // ] - AdvanceParser(); // ] +// return param; +// case NumberClass: +// param->ParameterType = ConstantParameter; +// param->InterpretedAs = ConstantParameter; - return param; - case NumberClass: - param->ParameterType = ConstantParameter; - param->InterpretedAs = ConstantParameter; +// param->Value.Number = token->Value.Number; - param->Value.Number = token->Value.Number; +// AdvanceParser(); - AdvanceParser(); +// return param; +// default: +// break; +// } - return param; - default: - break; - } +// return param; +// } - return param; -} +// Instruction* HandleOperation() { +// if (ParserAtEnd()) { +// //fprintf(stderr, "[Error] Expected instruction mnemonic\n"); +// return NULL; +// } -Instruction* HandleOperation() { - if (ParserAtEnd()) { - //fprintf(stderr, "[Error] Expected instruction mnemonic\n"); - return NULL; - } +// Token* token = PeekToken(); +// //char mn[12]; - Token* token = PeekToken(); - //char mn[12]; +// if (token->Class != MnemonicClass) { +// fprintf(stderr, "[Error] Line %d: Expected instruction mnemonic\n", token->LineNumber); +// IgnoreParserLine(); +// return NULL; +// } - if (token->Class != MnemonicClass) { - fprintf(stderr, "[Error] Line %d: Expected instruction mnemonic\n", token->LineNumber); - IgnoreParserLine(); - return NULL; - } +// Instruction* ins = CreateInstruction(token->Value.Mnemonic); - Instruction* ins = CreateInstruction(token->Value.Mnemonic); +// //GetMnemonicText(ins->Mnemonic, mn); - //GetMnemonicText(ins->Mnemonic, mn); +// AdvanceParser(); - AdvanceParser(); +// //No parameters here, we have a line break. +// if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) { +// goto InsertInstruction; +// } - //No parameters here, we have a line break. - if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) { - goto InsertInstruction; - } +// ins->ParameterOne = GetParameterType(); - ins->ParameterOne = GetParameterType(); +// 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); +// } - 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; +// } - goto InsertInstruction; - } +// if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) { +// 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); +// } - 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 - AdvanceParser(); //Consume the comma +// ins->ParameterTwo = GetParameterType(); - ins->ParameterTwo = GetParameterType(); +// InsertInstruction: - InsertInstruction: +// AddListItem(ins, MachineState.Instructions); - AddListItem(ins, MachineState.Instructions); +// AdvanceParser(); //Consume the line break - AdvanceParser(); //Consume the line break - - return ins; -} +// return ins; +// } void PrintSymbols(void) { - char mn[12]; + //char mn[12]; printf("-----SYMBOLS-----\n"); for(int i = 0; i < MachineState.SymbolsTable->Size; 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) { - case InstructionPointerSymbol: - GetMnemonicText(symbol->Value.Instruction->Mnemonic, mn); - printf("%s -> %s", symbol->Name, mn); - break; - case NumericSymbol: - printf("[N] %s Value: %d", symbol->Name, symbol->Value.Number); - break; - case StringSymbol: - if (symbol->Value.String->Terminated) - printf("[S] %s {%s}, %d", symbol->Name, symbol->Value.String->String, symbol->Value.String->TerminatingByte); - else - printf("[S] %s {%s}", symbol->Name, symbol->Value.String->String); - break; - case UnresolvedSymbol: - printf("[U] %s", symbol->Name); - break; - } + // switch(symbol->Type) { + // case InstructionPointerSymbol: + // GetMnemonicText(symbol->Value.Instruction->Mnemonic, mn); + // printf("%s -> %s", symbol->Name, mn); + // break; + // case NumericSymbol: + // printf("[N] %s Value: %d", symbol->Name, symbol->Value.Number); + // break; + // case StringSymbol: + // if (symbol->Value.String->Terminated) + // printf("[S] %s {%s}, %d", symbol->Name, symbol->Value.String->String, symbol->Value.String->TerminatingByte); + // else + // printf("[S] %s {%s}", symbol->Name, symbol->Value.String->String); + // break; + // case UnresolvedSymbol: + // printf("[U] %s", symbol->Name); + // break; + // } printf("\n"); } diff --git a/src/scanner.c b/src/scanner.c index f3c5011..bd27284 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -283,6 +283,14 @@ Token* ParseIdentifier(void) { 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); diff --git a/src/symbols_table.c b/src/symbols_table.c index bcd2a18..1013e94 100644 --- a/src/symbols_table.c +++ b/src/symbols_table.c @@ -25,7 +25,7 @@ SymbolTable* CreateSymbolTable(void){ return table; } -Symbol* CreateSymbol(char* name, SymbolType type) { +Symbol* CreateSymbol(char* name, int address, int resolved) { Symbol* symbol = calloc(1, sizeof(Symbol)); if (!symbol) { @@ -34,40 +34,29 @@ Symbol* CreateSymbol(char* name, SymbolType type) { return NULL; } - symbol->Type = type; + symbol->Address = address; symbol->Name = name; + symbol->Resolved = resolved; return symbol; } -SymbolString* CreateSymbolString(char* string, int terminated) { - if (!string) return NULL; +int TryGetSymbol(char* name, SymbolTable* table, Symbol** outSymbol) { + *outSymbol = NULL; - SymbolString* s = calloc(1, sizeof(SymbolString)); - - 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; + if (!name || !table) return 0; 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; 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) { - 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) { 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; } - Symbol* symbol = CreateSymbol(name, type); + Symbol* symbol = CreateSymbol(name, address, resolved); table->Symbols[table->Size] = symbol; table->Size++;