Updated the parser to be able to handle the changes made to the ISA.
This commit is contained in:
+3
-3
@@ -24,9 +24,9 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
DB,
|
DB,
|
||||||
Include,
|
Include,
|
||||||
Byte,
|
Byte
|
||||||
Load,
|
// Load,
|
||||||
Store
|
// Store
|
||||||
} Directive;
|
} Directive;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.db MAX_MEM 0xFFFF
|
.db MAX_MEM 0xFFFF
|
||||||
.db VIDEO_MEM 0xF37F
|
.db VIDEO_MEM 0xF37F
|
||||||
.db MAX_LENGTH MAX_MEM - MAX_LENGTH
|
;.db MAX_LENGTH MAX_MEM - MAX_LENGTH
|
||||||
.db MSG "Hello, World!", 0
|
.db MSG "Hello, World!", 0
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
@@ -9,7 +9,7 @@ _start:
|
|||||||
call strlen
|
call strlen
|
||||||
copy r1, MSG
|
copy r1, MSG
|
||||||
cmp r2, 0
|
cmp r2, 0
|
||||||
je _end
|
jz _end
|
||||||
cmp r2, MAX_LENGTH
|
cmp r2, MAX_LENGTH
|
||||||
jg _end
|
jg _end
|
||||||
draw_loop:
|
draw_loop:
|
||||||
@@ -18,7 +18,7 @@ draw_loop:
|
|||||||
inc r8
|
inc r8
|
||||||
dec r2
|
dec r2
|
||||||
cmp r2, 0
|
cmp r2, 0
|
||||||
je _end
|
jz _end
|
||||||
jmp draw_loop
|
jmp draw_loop
|
||||||
_end:
|
_end:
|
||||||
jmp _end
|
jmp _end
|
||||||
@@ -28,12 +28,14 @@ _end:
|
|||||||
; Returns: R2 - Contains the length of the string
|
; Returns: R2 - Contains the length of the string
|
||||||
strlen:
|
strlen:
|
||||||
copy r2, 0 ; length
|
copy r2, 0 ; length
|
||||||
cmp [r1], 0
|
copy byte r4, [r1]
|
||||||
je end ;The string is zero length
|
cmp r3, 0
|
||||||
|
jz end ;The string is zero length
|
||||||
loop:
|
loop:
|
||||||
inc r1
|
inc r1
|
||||||
cmp [r1], 0
|
copy byte r3, [r1]
|
||||||
je end
|
cmp r3, 0
|
||||||
|
jz end
|
||||||
inc r2
|
inc r2
|
||||||
jmp loop
|
jmp loop
|
||||||
end:
|
end:
|
||||||
|
|||||||
+3
-4
@@ -4,11 +4,10 @@
|
|||||||
.db msg "Hello, world!", 0
|
.db msg "Hello, world!", 0
|
||||||
.db NOTERM "No terminating byte here"
|
.db NOTERM "No terminating byte here"
|
||||||
.db null_byte 0
|
.db null_byte 0
|
||||||
|
jmp [r4]
|
||||||
;load r2, label
|
;load r2, label
|
||||||
something_insance:
|
something_insance:
|
||||||
load r1, unknown_symbol
|
load r1, unknown_symbol
|
||||||
load byte r1, r3
|
|
||||||
load r1, 5
|
load r1, 5
|
||||||
.db fun_alright 0x70;does this break?
|
.db fun_alright 0x70;does this break?
|
||||||
load r3, r4
|
load r3, r4
|
||||||
@@ -23,6 +22,6 @@ inc r1 ;increment r1
|
|||||||
xor r1, r1 ;clear self
|
xor r1, r1 ;clear self
|
||||||
pop r3
|
pop r3
|
||||||
jmp unknown_symbol
|
jmp unknown_symbol
|
||||||
jmp r4
|
jmp [r4]
|
||||||
jz unknown_symbol
|
jz [r6]
|
||||||
;And a comment at the end
|
;And a comment at the end
|
||||||
+112
-126
@@ -108,104 +108,6 @@ void HandleAssemblerDirective() {
|
|||||||
HeapSize += symbol->Length;
|
HeapSize += symbol->Length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Load:
|
|
||||||
{
|
|
||||||
AdvanceParser();
|
|
||||||
Token* reg = PeekToken();
|
|
||||||
|
|
||||||
if (reg->Class != RegisterClass && reg->Class != DirectiveClass) {
|
|
||||||
fprintf(stderr, "[Line %d] Syntax error, expected register or keyword 'byte'.\n", reg->LineNumber);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reg->Class == RegisterClass) {
|
|
||||||
AdvanceParser();
|
|
||||||
|
|
||||||
ExpectPuncuation(Comma, ForwardParser);
|
|
||||||
|
|
||||||
if (PeekToken()->Class != IdentifierClass && PeekToken()->Class != NumberClass && PeekToken()->Class != RegisterClass) {
|
|
||||||
fprintf(stderr, "[Line %d] Syntax error, expected either a symbol, numeric literal or a register.\n", PeekToken()->LineNumber);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PeekToken()->Class == NumberClass) {
|
|
||||||
directive->Class = MnemonicClass;
|
|
||||||
directive->Value.Mnemonic = COPYI;
|
|
||||||
directive->Lemexe = "copyi";
|
|
||||||
AdvanceParser(); //Number, register or identifier
|
|
||||||
}
|
|
||||||
else if (PeekToken()->Class == RegisterClass) {
|
|
||||||
directive->Class = MnemonicClass;
|
|
||||||
directive->Value.Mnemonic = COPY;
|
|
||||||
directive->Lemexe = "copy";
|
|
||||||
AdvanceParser(); //Number, register or identifier
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ExpectIdentifier(0, ForwardParser);
|
|
||||||
|
|
||||||
directive->Class = MnemonicClass;
|
|
||||||
directive->Value.Mnemonic = COPYA;
|
|
||||||
directive->Lemexe = "copya";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else if (reg->Class == DirectiveClass) {
|
|
||||||
// if (reg->Value.Directive != Byte) {
|
|
||||||
// fprintf(stderr, "[Line %d] Syntax error, expected keyword 'byte'.\n", reg->LineNumber);
|
|
||||||
// exit(3);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// RemoveCurrentToken(); //byte
|
|
||||||
|
|
||||||
// ExpectRegister();
|
|
||||||
|
|
||||||
// ExpectPuncuation(Comma, ForwardParser);
|
|
||||||
|
|
||||||
// ExpectRegister();
|
|
||||||
|
|
||||||
// directive->Class = MnemonicClass;
|
|
||||||
// directive->Value.Mnemonic = LODB;
|
|
||||||
// directive->Lemexe = "LODB";
|
|
||||||
// }
|
|
||||||
|
|
||||||
ExpectLineEndOrFileEnd(ForwardParser);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case Store:
|
|
||||||
{
|
|
||||||
AdvanceParser();
|
|
||||||
|
|
||||||
Token* next = PeekToken();
|
|
||||||
|
|
||||||
if (next->Class != DirectiveClass) {
|
|
||||||
//If the token after the current one is invalid then the expect function ahead will exit, so we can
|
|
||||||
//go ahead and change the STORE directive into a proper opcode here.
|
|
||||||
directive->Value.Mnemonic = COPY;
|
|
||||||
directive->Class = MnemonicClass;
|
|
||||||
directive->Lemexe = "copy";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (next->Value.Directive != Byte) {
|
|
||||||
fprintf(stderr, "[Line %d] Syntax error, expected keyword 'byte'.\n", next->LineNumber);
|
|
||||||
exit(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveCurrentToken(); //Remove byte modifier token.
|
|
||||||
|
|
||||||
directive->Value.Mnemonic = COPYB;
|
|
||||||
directive->Class = MnemonicClass;
|
|
||||||
directive->Lemexe = "copyb";
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpectRegister();
|
|
||||||
|
|
||||||
ExpectPuncuation(Comma, ForwardParser);
|
|
||||||
|
|
||||||
ExpectRegister();
|
|
||||||
|
|
||||||
ExpectLineEndOrFileEnd(ForwardParser);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Synatx error on line %d, %s.\n", directive->LineNumber, directive->Lemexe);
|
fprintf(stderr, "Synatx error on line %d, %s.\n", directive->LineNumber, directive->Lemexe);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -218,6 +120,86 @@ void HandleOpcode(void) {
|
|||||||
AdvanceParser();
|
AdvanceParser();
|
||||||
|
|
||||||
switch(opcode->Value.Mnemonic) {
|
switch(opcode->Value.Mnemonic) {
|
||||||
|
case COPY:
|
||||||
|
{
|
||||||
|
Token* arg = PeekToken();
|
||||||
|
int isByte = 0;
|
||||||
|
|
||||||
|
if (arg->Class == DirectiveClass) {
|
||||||
|
if (arg->Value.Directive != Byte) {
|
||||||
|
fprintf(stderr, "Syntax error on line %d: expected keyword 'byte'.\n", opcode->LineNumber);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
RemoveCurrentToken(); //byte
|
||||||
|
|
||||||
|
isByte = 1;
|
||||||
|
|
||||||
|
arg = PeekToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg->Class == RegisterClass) {
|
||||||
|
ExpectRegister();
|
||||||
|
|
||||||
|
ExpectPuncuation(Comma, ForwardParser);
|
||||||
|
|
||||||
|
arg = PeekToken();
|
||||||
|
|
||||||
|
if (arg->Class == NumberClass) {
|
||||||
|
opcode->Value.Mnemonic = isByte ? COPYB : COPYI;
|
||||||
|
opcode->Lemexe = isByte ? "copyb" : "copyi";
|
||||||
|
|
||||||
|
AdvanceParser();
|
||||||
|
}
|
||||||
|
else if (arg->Class == RegisterClass) {
|
||||||
|
if (isByte) {
|
||||||
|
fprintf(stderr, "Syntax error on line %d: unexpected modifier 'Byte' for Register to Register copy.\n", opcode->LineNumber);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpectRegister();
|
||||||
|
|
||||||
|
opcode->Value.Mnemonic = COPY;
|
||||||
|
opcode->Lemexe = "copy";
|
||||||
|
}
|
||||||
|
else if (arg->Class & IdentifierClass) {
|
||||||
|
opcode->Value.Mnemonic = isByte ? COPYAB : COPYA;
|
||||||
|
opcode->Lemexe = isByte ? "copyab" : "copya";
|
||||||
|
|
||||||
|
AdvanceParser();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ExpectPuncuation(LBracket, ForwardParser);
|
||||||
|
|
||||||
|
ExpectRegister();
|
||||||
|
|
||||||
|
ExpectPuncuation(RBracket, ForwardParser);
|
||||||
|
|
||||||
|
opcode->Value.Mnemonic = isByte ? COPYRAB : COPYRA;
|
||||||
|
opcode->Lemexe = isByte ? "copyrab" : "copyra";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ExpectPuncuation(LBracket, ForwardParser);
|
||||||
|
|
||||||
|
ExpectRegister();
|
||||||
|
|
||||||
|
ExpectPuncuation(RBracket, ForwardParser);
|
||||||
|
|
||||||
|
ExpectPuncuation(Comma, ForwardParser);
|
||||||
|
|
||||||
|
ExpectPuncuation(LBracket, ForwardParser);
|
||||||
|
|
||||||
|
ExpectRegister();
|
||||||
|
|
||||||
|
ExpectPuncuation(RBracket, ForwardParser);
|
||||||
|
|
||||||
|
opcode->Value.Mnemonic = isByte ? COPYRARAB : COPYRARA;
|
||||||
|
opcode->Lemexe = isByte ? "copyrarab" : "copyrara";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CMP:
|
case CMP:
|
||||||
{
|
{
|
||||||
ExpectRegister();
|
ExpectRegister();
|
||||||
@@ -226,7 +208,7 @@ void HandleOpcode(void) {
|
|||||||
|
|
||||||
TokenClass class = PeekToken()->Class;
|
TokenClass class = PeekToken()->Class;
|
||||||
|
|
||||||
if (class == NumberClass) {
|
if (class == NumberClass || class & IdentifierClass) {
|
||||||
opcode->Value.Mnemonic = CMPI;
|
opcode->Value.Mnemonic = CMPI;
|
||||||
opcode->Lemexe = "CMPI";
|
opcode->Lemexe = "CMPI";
|
||||||
|
|
||||||
@@ -272,55 +254,59 @@ void HandleOpcode(void) {
|
|||||||
{
|
{
|
||||||
Token* arg = PeekToken();
|
Token* arg = PeekToken();
|
||||||
|
|
||||||
opcode->Value.Mnemonic = JMPI;
|
if (arg->Class & IdentifierClass) {
|
||||||
opcode->Lemexe = "jmpi";
|
|
||||||
|
|
||||||
if (arg->Class == IdentifierClass) {
|
|
||||||
ExpectIdentifier(0, ForwardParser);
|
ExpectIdentifier(0, ForwardParser);
|
||||||
|
|
||||||
opcode->Value.Mnemonic = JMP;
|
opcode->Value.Mnemonic = JMP;
|
||||||
opcode->Lemexe = "jmp";
|
opcode->Lemexe = "jmp";
|
||||||
}
|
}
|
||||||
else ExpectRegister();
|
else
|
||||||
|
{
|
||||||
|
ExpectPuncuation(LBracket, ForwardParser);
|
||||||
|
|
||||||
|
ExpectRegister();
|
||||||
|
|
||||||
|
ExpectPuncuation(RBracket, ForwardParser);
|
||||||
|
|
||||||
|
opcode->Value.Mnemonic = JMPI;
|
||||||
|
opcode->Lemexe = "jmpi";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JZ:
|
case JZ:
|
||||||
{
|
{
|
||||||
Token* arg = PeekToken();
|
ExpectIdentifier(0, ForwardParser);
|
||||||
|
|
||||||
if (arg->Class == IdentifierClass) {
|
opcode->Value.Mnemonic = JZ;
|
||||||
ExpectIdentifier(0, ForwardParser);
|
opcode->Lemexe = "jz";
|
||||||
|
|
||||||
opcode->Value.Mnemonic = JZ;
|
|
||||||
opcode->Lemexe = "jz";
|
|
||||||
}
|
|
||||||
else ExpectRegister();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JG:
|
case JG:
|
||||||
{
|
{
|
||||||
Token* arg = PeekToken();
|
ExpectIdentifier(0, ForwardParser);
|
||||||
|
opcode->Value.Mnemonic = JG;
|
||||||
if (arg->Class == IdentifierClass) {
|
opcode->Lemexe = "jg";
|
||||||
ExpectIdentifier(0, ForwardParser);
|
|
||||||
|
|
||||||
opcode->Value.Mnemonic = JG;
|
|
||||||
opcode->Lemexe = "jg";
|
|
||||||
}
|
|
||||||
else ExpectRegister();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JL:
|
case JL:
|
||||||
|
{
|
||||||
|
ExpectIdentifier(0, ForwardParser);
|
||||||
|
|
||||||
|
opcode->Value.Mnemonic = JL;
|
||||||
|
opcode->Lemexe = "jl";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CALL:
|
||||||
{
|
{
|
||||||
Token* arg = PeekToken();
|
Token* arg = PeekToken();
|
||||||
|
|
||||||
if (arg->Class == IdentifierClass) {
|
if ((arg->Class & IdentifierClass) == 0) {
|
||||||
ExpectIdentifier(0, ForwardParser);
|
fprintf(stderr, "Syntax error on line %d: expected subroutine call target.\n", opcode->LineNumber);
|
||||||
|
|
||||||
opcode->Value.Mnemonic = JL;
|
exit(1);
|
||||||
opcode->Lemexe = "jl";
|
|
||||||
}
|
}
|
||||||
else ExpectRegister();
|
|
||||||
|
ExpectIdentifier(0, ForwardParser);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
+12
-12
@@ -283,14 +283,14 @@ Token* ParseIdentifier(void) {
|
|||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
if (strcmp(lexeme, "load") == 0) {
|
// if (strcmp(lexeme, "load") == 0) {
|
||||||
Token* token = CreateToken(Line, DirectiveClass);
|
// Token* token = CreateToken(Line, DirectiveClass);
|
||||||
|
|
||||||
token->Lemexe = lexeme;
|
// token->Lemexe = lexeme;
|
||||||
token->Value.Directive = Load;
|
// token->Value.Directive = Load;
|
||||||
|
|
||||||
return token;
|
// return token;
|
||||||
}
|
// }
|
||||||
if (strcmp(lexeme, "byte") == 0) {
|
if (strcmp(lexeme, "byte") == 0) {
|
||||||
Token* token = CreateToken(Line, DirectiveClass);
|
Token* token = CreateToken(Line, DirectiveClass);
|
||||||
|
|
||||||
@@ -299,14 +299,14 @@ Token* ParseIdentifier(void) {
|
|||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
if (strcmp(lexeme, "store") == 0) {
|
// if (strcmp(lexeme, "store") == 0) {
|
||||||
Token* token = CreateToken(Line, DirectiveClass);
|
// Token* token = CreateToken(Line, DirectiveClass);
|
||||||
|
|
||||||
token->Lemexe = lexeme;
|
// token->Lemexe = lexeme;
|
||||||
token->Value.Directive = Store;
|
// token->Value.Directive = Store;
|
||||||
|
|
||||||
return token;
|
// return token;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Token* token = CreateToken(Line, IdentifierClass);
|
Token* token = CreateToken(Line, IdentifierClass);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user