Updated the parser to handle treating variables as expressions. Updated the symbols table to handle computing the values of variables.
This commit is contained in:
@@ -38,7 +38,7 @@ int TryGetSymbol(const char* name, const SymbolTable* table, Symbol** outSymbol)
|
||||
Symbol* AddSymbolToTable(const char* name, int address, SymbolTable* table);
|
||||
void FreeSymbolTable(SymbolTable* table);
|
||||
void FreeSymbol(Symbol* symbol);
|
||||
int SymbolResolved(const Symbol* symbol);
|
||||
int SymbolResolved(const Symbol* symbol, const SymbolTable* table);
|
||||
int TryGetSymbolValue(const Symbol* symbol, const SymbolTable* table, unsigned short* value);
|
||||
|
||||
#endif
|
||||
+12
-34
@@ -59,31 +59,25 @@ void ParseTokens(TokenList* tokens, SymbolTable** symbols) {
|
||||
Symbol* symbol;
|
||||
int found = TryGetSymbol(t->Lemexe, SymbolsTable, &symbol);
|
||||
|
||||
if (found && SymbolResolved(symbol)) {
|
||||
if (found && SymbolResolved(symbol, SymbolsTable)) {
|
||||
fprintf(stderr, "[Error] Line %d: Redefinition of symbol '%s'\n", t->LineNumber, t->Lemexe);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!found) symbol = AddSymbolToTable(t->Lemexe, PC, SymbolsTable);
|
||||
// else
|
||||
// {
|
||||
symbol->Address = PC;
|
||||
//symbol->Type = RefPointer;
|
||||
//symbol->Token = t;
|
||||
//}
|
||||
|
||||
symbol->Address = PC;
|
||||
|
||||
RemoveCurrentToken(); //label
|
||||
|
||||
ExpectLineEndOrFileEnd(RemoveExpected);
|
||||
|
||||
//symbol->Value.Mnemonic = ExpectMnemonic();
|
||||
symbol->Token = ExpectMnemonic();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
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();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -103,22 +97,12 @@ void HandleAssemblerDirective() {
|
||||
|
||||
if (PeekToken()->Class == CharacterClass) {
|
||||
ExpectCharacterClass(symbol);
|
||||
|
||||
//symbol->Type = RefLiteral;
|
||||
}
|
||||
else if (PeekToken()->Class == NumberClass || PeekToken()->Class == IdentifierClass) {
|
||||
symbol->Length = 2;
|
||||
|
||||
//RemoveCurrentToken(); //Clear the number token.
|
||||
|
||||
//ExpectLineEndOrFileEnd(RemoveExpected);
|
||||
|
||||
//symbol->Type = RefLiteral;
|
||||
|
||||
symbol->ValueExpression = ParseSymbolExpression();
|
||||
}
|
||||
|
||||
//HeapSize += symbol->Length;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -425,22 +409,14 @@ Symbol* ExpectIdentifier(ExpectOptions options, int expectUnresolved) {
|
||||
|
||||
int found = TryGetSymbol(token->Lemexe, SymbolsTable, &symbol);
|
||||
|
||||
if (found && SymbolResolved(symbol) && expectUnresolved) {
|
||||
if (found && TryGetSymbolValue(symbol, SymbolsTable, NULL) && expectUnresolved) {
|
||||
fprintf(stderr, "[Line %d] Redefinition of symbol '%s'.\n", token->LineNumber, token->Lemexe);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
//symbol->Resolved = resolved || symbol->Resolved(symbol);
|
||||
symbol = AddSymbolToTable(token->Lemexe, PC, SymbolsTable);
|
||||
}
|
||||
|
||||
if (!found) symbol = AddSymbolToTable(token->Lemexe, PC, SymbolsTable);
|
||||
if (expectUnresolved) symbol->Token = token;
|
||||
|
||||
// else {
|
||||
// symbol = AddSymbolToTable(token->Lemexe, PC, SymbolsTable);
|
||||
// }
|
||||
|
||||
if (options & RemoveExpected) RemoveCurrentToken();
|
||||
if (options & ForwardParser) AdvanceParser();
|
||||
|
||||
@@ -456,6 +432,7 @@ void ExpectCharacterClass(Symbol* symbol) {
|
||||
}
|
||||
|
||||
symbol->Length = strlen(token->Lemexe);
|
||||
symbol->Token = token;
|
||||
|
||||
RemoveCurrentToken(); //Remove the string declared by this DB command.
|
||||
|
||||
@@ -506,7 +483,9 @@ void PrintSymbols(void) {
|
||||
for(int i = 0; i < SymbolsTable->Size; i++) {
|
||||
Symbol* symbol = SymbolsTable->Symbols[i];
|
||||
unsigned short value = 0;
|
||||
int resolved = TryGetSymbolValue(symbol, SymbolsTable, &value);
|
||||
int resolved = SymbolResolved(symbol, SymbolsTable);
|
||||
|
||||
if (resolved) TryGetSymbolValue(symbol, SymbolsTable, &value);
|
||||
|
||||
printf("[%s] %s [Value: %d]", resolved == 0 ? "Unresolved" : "Resolved", symbol->Name, value);
|
||||
|
||||
@@ -569,12 +548,12 @@ TokenNode* ParseSymbolExpression(void) {
|
||||
|
||||
TokenNode* value = CreateTokenNode(ExpectMathOperand(RemoveExpected));
|
||||
TokenNode* operation = CreateTokenNode(ExpectMathOperator(RemoveExpected));
|
||||
|
||||
|
||||
operation->Left = root;
|
||||
operation->Right = value;
|
||||
root = operation;
|
||||
}
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -621,8 +600,7 @@ Token* ExpectMathOperand(ExpectOptions options) {
|
||||
fprintf(stderr, "[Line %d] Syntax error, expected a number or identifier.\n", token->LineNumber);
|
||||
exit (1);
|
||||
}
|
||||
//TODO: handle symbols.
|
||||
|
||||
|
||||
if (options & RemoveExpected) RemoveCurrentToken();
|
||||
if (options & ForwardParser) AdvanceParser();
|
||||
|
||||
|
||||
+49
-30
@@ -3,21 +3,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int SymbolResolved(const Symbol* symbol) {
|
||||
int SymbolResolved(const Symbol* symbol, const SymbolTable* table) {
|
||||
if (!symbol) return 0;
|
||||
|
||||
return symbol->Token != NULL;
|
||||
const Token* token = symbol->Token;
|
||||
|
||||
// switch (symbol->Type) {
|
||||
// case RefLiteral:
|
||||
// return 1;
|
||||
// case RefExpression:
|
||||
// return 0;
|
||||
// case RefPointer:
|
||||
// return symbol->Value.Mnemonic != 0;
|
||||
// default:
|
||||
// return 0;
|
||||
// }
|
||||
if (!token) return 0;
|
||||
|
||||
if (token->Class == LabelClass || token->Class == CharacterClass || token->Class == MnemonicClass) return 1;
|
||||
|
||||
return TryGetSymbolValue(symbol, table, NULL);
|
||||
}
|
||||
|
||||
SymbolTable* CreateSymbolTable(void){
|
||||
@@ -120,53 +115,59 @@ void FreeSymbol(Symbol* symbol) {
|
||||
}
|
||||
|
||||
int TryGetTokenNodeValue(const TokenNode* node, const SymbolTable* table, unsigned short* value);
|
||||
unsigned short DoOp(unsigned short left, unsigned short right, TokenPunctuation op);
|
||||
|
||||
int TryGetSymbolValue(const Symbol* symbol, const SymbolTable* table, unsigned short* value) {
|
||||
if (!symbol || !symbol->Token || !table) return 0;
|
||||
if (symbol->Token->Class == CharacterClass) return 0;
|
||||
|
||||
unsigned short left = 0;
|
||||
unsigned short right = 0;
|
||||
|
||||
TokenNode* root = symbol->ValueExpression;
|
||||
Symbol* s = NULL;
|
||||
if (value) *value = 0;
|
||||
|
||||
if (!root || !root->Token) return 0;
|
||||
|
||||
switch (root->Token->Class) {
|
||||
case NumberClass:
|
||||
*value = root->Token->Value.Number;
|
||||
if (value) *value = root->Token->Value.Number;
|
||||
|
||||
return 1;
|
||||
case LabelClass:
|
||||
case IdentifierClass:
|
||||
if (!TryGetSymbol(root->Token->Lemexe, table, &s)) return 0;
|
||||
|
||||
if (!TryGetSymbolValue(s, table, value)) return 0;
|
||||
|
||||
return 1;
|
||||
return TryGetTokenNodeValue(s->ValueExpression, table, value);
|
||||
case PunctuationClass:
|
||||
if (!TryGetTokenNodeValue(root->Left, table, &left)) return 0;
|
||||
if (!TryGetTokenNodeValue(root->Right, table, &right)) return 0;
|
||||
|
||||
*value = left + right;
|
||||
break;
|
||||
return TryGetTokenNodeValue(root, table, value);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TryGetTokenNodeValue(const TokenNode* node, const SymbolTable* table, unsigned short* value) {
|
||||
const Token* token = node->Token;
|
||||
Symbol* symbol = { 0 };
|
||||
|
||||
if (token->Class == NumberClass) {
|
||||
*value = token->Value.Number;
|
||||
if (value) *value = token->Value.Number;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (token->Class == IdentifierClass) {
|
||||
if (!TryGetSymbol(token->Lemexe, table, &symbol)) return 0;
|
||||
|
||||
return TryGetTokenNodeValue(symbol->ValueExpression, table, value);
|
||||
}
|
||||
|
||||
if (token->Class != PunctuationClass) return 0;
|
||||
|
||||
unsigned short left = 0;
|
||||
unsigned short right = 0;
|
||||
|
||||
if (!TryGetTokenNodeValue(node->Left, table, &left)) return 0;
|
||||
if (!TryGetTokenNodeValue(node->Right, table, &right)) return 0;
|
||||
|
||||
if (value) *value = DoOp(left, right, token->Value.Punctuation);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
TokenNode* CreateTokenNode(const Token* token){
|
||||
@@ -181,3 +182,21 @@ TokenNode* CreateTokenNode(const Token* token){
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
unsigned short DoOp(unsigned short left, unsigned short right, TokenPunctuation op) {
|
||||
switch (op) {
|
||||
case Plus:
|
||||
return left + right;
|
||||
case Minus:
|
||||
return left - right;
|
||||
case Star:
|
||||
return left * right;
|
||||
case Slash:
|
||||
return left / right;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user