refactor some things to fix things (maybe)
This commit is contained in:
@@ -42,6 +42,104 @@ InstructionOpcode stringToInstructionOpcode(const char* string) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void processBufferedToken(
|
||||
char* buf,
|
||||
size_t bufSize,
|
||||
Instruction* instruction,
|
||||
bool* processingInstWord,
|
||||
uint8_t* processingArgNum
|
||||
) {
|
||||
if (*processingInstWord) {
|
||||
instruction->opcode = stringToInstructionOpcode(buf);
|
||||
*processingInstWord = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*processingArgNum >= 3) {
|
||||
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
OperandType type = INSTRUCTION_OPERAND_TYPES[instruction->opcode][*processingArgNum];
|
||||
switch (type) {
|
||||
case OP_NONE: {
|
||||
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
case OP_REG: {
|
||||
if (bufSize > 1) {
|
||||
fprintf(stderr, "expecting register identifier, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
switch (buf[0]) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
instruction->operands[*processingArgNum] = REG_A;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
instruction->operands[*processingArgNum] = REG_B;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
instruction->operands[*processingArgNum] = REG_C;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
instruction->operands[*processingArgNum] = REG_X;
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
instruction->operands[*processingArgNum] = REG_Y;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
instruction->operands[*processingArgNum] = REG_Z;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
instruction->operands[*processingArgNum] = REG_R;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
instruction->operands[*processingArgNum] = REG_F;
|
||||
break;
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "expecting register identifier, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_IMM4: {
|
||||
char* endptr;
|
||||
long value = strtol(buf, &endptr, 0);
|
||||
if (endptr == (char*)buf) {
|
||||
fprintf(stderr, "couldn't convert %s to a number\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
if (value < 0 || value > 0xF) {
|
||||
fprintf(stderr, "%s is out of range for a 4-bit immediate\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
instruction->operands[*processingArgNum] = (Register)value;
|
||||
break;
|
||||
}
|
||||
case OP_IMM16: {
|
||||
char* endptr;
|
||||
instruction->immediate = strtol(buf, &endptr, 0);
|
||||
instruction->hasImm16 = true;
|
||||
if (endptr == (char*)buf) {
|
||||
fprintf(stderr, "couldn't convert %s to a number\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*processingArgNum)++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Essentially a lexer for the assembly language.
|
||||
* @param [input] The text to create a program from. NOT the file name
|
||||
@@ -72,79 +170,7 @@ Program createProgramFromText(const char* input) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (processingInstWord) {
|
||||
instruction.opcode = stringToInstructionOpcode(buf);
|
||||
processingInstWord = false;
|
||||
} else {
|
||||
if (processingArgNum >= 3) {
|
||||
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
OperandType type = INSTRUCTION_OPERAND_TYPES[instruction.opcode][processingArgNum];
|
||||
switch (type) {
|
||||
case OP_NONE: {
|
||||
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
case OP_REG: {
|
||||
if (bufSize > 1) {
|
||||
fprintf(stderr, "expecting register identifier, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
switch (buf[0]) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
instruction.operands[processingArgNum] = REG_A;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
instruction.operands[processingArgNum] = REG_B;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
instruction.operands[processingArgNum] = REG_C;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
instruction.operands[processingArgNum] = REG_X;
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
instruction.operands[processingArgNum] = REG_Y;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
instruction.operands[processingArgNum] = REG_Z;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
instruction.operands[processingArgNum] = REG_R;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
instruction.operands[processingArgNum] = REG_F;
|
||||
break;
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "expecting register identifier, got %s\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_IMM16: {
|
||||
char* endptr;
|
||||
instruction.immediate = strtol(buf, &endptr, 0);
|
||||
instruction.hasImm16 = true;
|
||||
if (endptr == (char*)buf) {
|
||||
fprintf(stderr, "couldn't convert %s to a number\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
processingArgNum++;
|
||||
}
|
||||
processBufferedToken(buf, bufSize, &instruction, &processingInstWord, &processingArgNum);
|
||||
|
||||
buf[0] = '\0';
|
||||
bufSize = 0;
|
||||
@@ -155,6 +181,9 @@ Program createProgramFromText(const char* input) {
|
||||
// Ignore extra new lines
|
||||
break;
|
||||
}
|
||||
if (bufSize > 0) {
|
||||
processBufferedToken(buf, bufSize, &instruction, &processingInstWord, &processingArgNum);
|
||||
}
|
||||
addInstructionToProgram(&program, instruction);
|
||||
instruction = (Instruction){};
|
||||
processingInstWord = true;
|
||||
@@ -198,6 +227,12 @@ Program createProgramFromText(const char* input) {
|
||||
|
||||
current++;
|
||||
if (current >= programLen) {
|
||||
if (!(processingInstWord && bufSize == 0)) {
|
||||
if (bufSize > 0) {
|
||||
processBufferedToken(buf, bufSize, &instruction, &processingInstWord, &processingArgNum);
|
||||
}
|
||||
addInstructionToProgram(&program, instruction);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user