Files
assm-test/src/parser.c
T

312 lines
8.9 KiB
C

#include "../includes/parser.h"
const List* TokensList;
int CurrentToken = 0;
void PrintSymbols(void);
<<<<<<< Updated upstream
void HandleOperation(void);
=======
SymbolString* ParseIdentifierParameter(void);
Instruction* HandleOperation(void);
>>>>>>> Stashed changes
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:
<<<<<<< Updated upstream
AdvanceParser();
AddSymbolToTable(t->Lemexe, NULL, strlen(t->Lemexe), MachineState.SymbolsTable)->Resolved = 1;
AdvanceParser(); //Consume the NewLine
=======
{
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;
}
>>>>>>> Stashed changes
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;
<<<<<<< Updated upstream
case LabelClass:
=======
>>>>>>> Stashed changes
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();
}
}