From b810d7803cfc472149742e7806f0544c031e6f34 Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Thu, 31 Aug 2023 23:27:33 -0500 Subject: [PATCH] Updated the parser to create an expression tree for symbols declared via .db directives. Scanner now see some math operators as 'punctuation'. --- src/parser.c | 96 +++++++++++++++++++++++++++++++++++++++------ src/scanner.c | 16 ++++++++ src/symbols_table.c | 4 +- 3 files changed, 100 insertions(+), 16 deletions(-) diff --git a/src/parser.c b/src/parser.c index a7355de..db2e0c6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -24,8 +24,11 @@ void ExpectRegister(void); Symbol* ExpectIdentifier(ExpectOptions options, int expectUnresolved); void ExpectCharacterClass(Symbol* symbol); Token* ExpectLineEndOrFileEnd(ExpectOptions options); +Token* ExpectMathOperator(ExpectOptions options); +Token* ExpectMathOperand(ExpectOptions options); SymbolTable* SymbolsTable; +TokenNode* ParseSymbolExpression(void); //int HeapSize = 0; int PC = 0; @@ -103,24 +106,16 @@ void HandleAssemblerDirective() { //symbol->Type = RefLiteral; } - else if (PeekToken()->Class == NumberClass) { + else if (PeekToken()->Class == NumberClass || PeekToken()->Class == IdentifierClass) { symbol->Length = 2; - RemoveCurrentToken(); //Clear the number token. + //RemoveCurrentToken(); //Clear the number token. - ExpectLineEndOrFileEnd(RemoveExpected); + //ExpectLineEndOrFileEnd(RemoveExpected); //symbol->Type = RefLiteral; - } - else if (PeekToken()->Class == IdentifierClass) { - //symbol->Type = RefExpression; - symbol = ExpectIdentifier(RemoveExpected, 0); - symbol->Length = 2; - - //TODO: This needs to be expanded to handle expressions, a symbol to symbol reg is not allowed. - - ExpectLineEndOrFileEnd(RemoveExpected); + symbol->ValueExpression = ParseSymbolExpression(); } //HeapSize += symbol->Length; @@ -510,8 +505,10 @@ void PrintSymbols(void) { printf("-----SYMBOLS-----\n"); for(int i = 0; i < SymbolsTable->Size; i++) { Symbol* symbol = SymbolsTable->Symbols[i]; + unsigned short value = 0; + int resolved = TryGetSymbolValue(symbol, SymbolsTable, &value); - printf("[%s] %s [Width: %d]", SymbolResolved(symbol) == 0 ? "Unresolved" : "Resolved", symbol->Name, symbol->Length); + printf("[%s] %s [Value: %d]", resolved == 0 ? "Unresolved" : "Resolved", symbol->Name, value); if (symbol->Token && symbol->Token->Class == MnemonicClass) { @@ -557,4 +554,77 @@ void IgnoreParserLine(void) { void RemoveCurrentToken(void) { RemoveToken(CurrentToken, TokensList); +} + +TokenNode* ParseSymbolExpression(void) { + TokenNode* root = CreateTokenNode(ExpectMathOperand(RemoveExpected)); + + while(!ParserAtEnd()) { + if (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine) { + + ExpectPuncuation(NewLine, RemoveExpected); + + break; + } + + TokenNode* value = CreateTokenNode(ExpectMathOperand(RemoveExpected)); + TokenNode* operation = CreateTokenNode(ExpectMathOperator(RemoveExpected)); + + operation->Left = root; + operation->Right = value; + root = operation; + } + + return root; +} + +Token* ExpectMathOperator(ExpectOptions options) { + if (ParserAtEnd()) { + fprintf(stderr, "Syntax error, expected math operator but found unexpected end of file.\n"); + exit (1); + } + + Token* current = PeekToken(); + + if (current->Class != PunctuationClass) { + fprintf(stderr, "[Line %d] Syntax error, expected math operator.\n", current->LineNumber); + exit (1); + } + + switch (current->Value.Punctuation) { + case Plus: + case Minus: + case Star: + case Slash: + case Power: + break; + default: + fprintf(stderr, "[Line %d] Syntax error, expected math operator 2.\n", current->LineNumber); + exit(1); + } + + if (options & RemoveExpected) RemoveCurrentToken(); + if (options & ForwardParser) AdvanceParser(); + + return current; +} + +Token* ExpectMathOperand(ExpectOptions options) { + if (ParserAtEnd()) { + fprintf(stderr, "Syntax error, expected math operand but found unexpected end of file.\n"); + exit (1); + } + + Token* token = PeekToken(); + + if (token->Class != NumberClass && token->Class != IdentifierClass) { + 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(); + + return token; } \ No newline at end of file diff --git a/src/scanner.c b/src/scanner.c index 8dd8346..c507cd2 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -328,6 +328,10 @@ int IsPunctuation(char c) { case '(': case ')': case ',': + case '-': + case '+': + case '*': + case '/': return 1; default: return 0; @@ -366,6 +370,18 @@ Token* ParsePunctuation(char c) { case ',': punctuation = Comma; break; + case '-': + punctuation = Minus; + break; + case '+': + punctuation = Plus; + break; + case '*': + punctuation = Star; + break; + case '/': + punctuation = Slash; + break; default: return NULL; } diff --git a/src/symbols_table.c b/src/symbols_table.c index 46400b7..959148d 100644 --- a/src/symbols_table.c +++ b/src/symbols_table.c @@ -136,7 +136,6 @@ int TryGetSymbolValue(const Symbol* symbol, const SymbolTable* table, unsigned s *value = root->Token->Value.Number; return 1; - break; case LabelClass: case IdentifierClass: if (!TryGetSymbol(root->Token->Lemexe, table, &s)) return 0; @@ -144,8 +143,7 @@ int TryGetSymbolValue(const Symbol* symbol, const SymbolTable* table, unsigned s if (!TryGetSymbolValue(s, table, value)) return 0; return 1; - break; - case PunctuationClass: //TODO: ()'s need to be handled + case PunctuationClass: //check for math operator if (!TryGetSymbol(root->Left->Token->Lemexe, table, &s)) return 0;