312 lines
8.9 KiB
C
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();
|
|
}
|
|
} |