#include "../includes/parser.h" const List* TokensList; int CurrentToken = 0; void PrintSymbols(void); SymbolString* ParseIdentifierParameter(void); Instruction* HandleOperation(void); void HandleAssemblerDirective(void); void AdvanceParser(void); void IgnoreParserLine(void); Token* PeekToken(void); int ParserAtEnd(void); IRState MachineState; IRState* ParseTokens(List* tokens) { if (!tokens) return NULL; TokensList = tokens; MachineState.SymbolsTable = CreateSymbolTable(); MachineState.Instructions = CreateList(); while(!ParserAtEnd()) { Token* t = PeekToken(); switch(t->Class) { case DirectiveClass: //Maybe these should be ignored, let another process handle that. IgnoreParserLine(); break; case MnemonicClass: HandleOperation(); break; case LabelClass: { Symbol* symbol = TryGetSymbol(t->Lemexe, MachineState.SymbolsTable); if (symbol && symbol->Resolved) { fprintf(stderr, "[Error] Line %d: Redefinition of symbol '%s'\n", t->LineNumber, t->Lemexe); exit(1); } AdvanceParser(); //Consume the label token if (!symbol) AddSymbolToTable(t->Lemexe, MachineState.SymbolsTable)->Resolved = 1; else symbol->Resolved = 1; AdvanceParser(); //Consume the NewLine // Instruction* ins = HandleOperation(); // if (!ins) continue; // symbol->Value.Instruction = ins; // symbol->InstructionPointer = 1; } 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; } } if (MachineState.SymbolsTable->Size > 0) PrintSymbols(); for(int i = 0; i < MachineState.Instructions->size; i++) { char mn[12]; Instruction* ins = MachineState.Instructions->content[i]; GetMnemonicText(ins->Mnemonic, mn); printf("%s\n", mn); } return &MachineState; } SymbolString* ParseIdentifierParameter(void) { Token* token = PeekToken(); if (token->Class != IdentifierClass) { fprintf(stderr, "[Error] Line %d: Expected identifier\n", token->LineNumber); IgnoreParserLine(); return NULL; } SymbolString* string = CreateSymbolString(token->Lemexe); AdvanceParser(); if (token->Class == PunctuationClass && token->Value.Punctuation == NewLine) { return string; } else if (token->Class == PunctuationClass && token->Value.Punctuation == Comma) { AdvanceParser(); // Comsume the comma token = PeekToken(); if (token->Class != NumberClass) { fprintf(stderr, "[Error] Line %d: Expected string termination number.\n", token->LineNumber); IgnoreParserLine(); free(string); return NULL; } string->HasTerminatorByte = 1; string->TerminatorByte = token->Value.Number; return string; } return NULL; } Parameter* GetParameterType() { Token* token = PeekToken(); Symbol* symbol = NULL; Parameter* param = CreateParameter(NoParameter); switch(token->Class) { case RegisterClass: param->ParameterType = RegisterParameter; param->InterpretedAs = RegisterParameter; param->Value.Register = token->Value.Register; AdvanceParser(); return param; case IdentifierClass: param->ParameterType = AddressParameter; param->InterpretedAs = AddressParameter; symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); if (!symbol) symbol = AddSymbolToTable(token->Lemexe, MachineState.SymbolsTable); param->Value.Symbol = symbol; 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->ParameterType = AddressParameter; symbol = TryGetSymbol(token->Lemexe, MachineState.SymbolsTable); if (!symbol) symbol = AddSymbolToTable(token->Lemexe, MachineState.SymbolsTable); param->Value.Symbol = symbol; } 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. token = PeekToken(); if (token->Class != PunctuationClass || token->Value.Punctuation != RBracket) { fprintf(stderr, "[Error] Line %d: Expected closing bracket.\n", token->LineNumber); exit(1); } AdvanceParser(); // ] return param; case NumberClass: param->ParameterType = ConstantParameter; param->InterpretedAs = ConstantParameter; param->Value.Number = token->Value.Number; AdvanceParser(); return param; default: break; } return param; } void HandleOperation() { Token* token = PeekToken(); char mn[12]; Instruction* ins = CreateInstruction(token->Value.Mnemonic); GetMnemonicText(ins->Mnemonic, mn); AdvanceParser(); //No parameters here, we have a line break. if (PeekToken()->EndOfFile || (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine)) { goto InsertInstruction; } 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); } goto InsertInstruction; } if (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.\n", token->LineNumber); exit(1); } AdvanceParser(); //Consume the comma ins->ParameterTwo = GetParameterType(); InsertInstruction: AddListItem(ins, sizeof(Instruction), MachineState.Instructions); AdvanceParser(); //Consume the line break free(ins); } void PrintSymbols(void) { printf("-----SYMBOLS-----\n"); for(int i = 0; i < MachineState.SymbolsTable->Size; i++) { Symbol* symbol = MachineState.SymbolsTable->Symbols[i]; printf("[Resolved? %d] %s\n", symbol->Resolved, symbol->Name); } printf("-----SYMBOLS-----\n"); } 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]; } void IgnoreParserLine(void) { while(!ParserAtEnd()) { if (PeekToken()->Class == PunctuationClass && PeekToken()->Value.Punctuation == NewLine) { AdvanceParser(); break; } if (PeekToken()->EndOfFile) break; AdvanceParser(); } }