all repos — nand2tetris @ 45c796329ee858875dffb68a81155d43a8556c18

my nand2tetris progress

Ignore dest field reg order, more error() changes
x1phosura x1phosura@x1phosura.zone
Sun, 25 Dec 2022 15:20:53 -0800
commit

45c796329ee858875dffb68a81155d43a8556c18

parent

12d25839d7f116d96cc707c24a1ac01332797f7b

1 files changed, 64 insertions(+), 73 deletions(-)

jump to
M projects/06/assembler1/assembler1.cprojects/06/assembler1/assembler1.c

@@ -9,7 +9,9 @@

//#define DEBUG(...) printf(__VA_ARGS__) #define DEBUG(...) #define die(err_msg) perror(err_msg); exit(-1) -#define alert(...) fprintf(stderr, __VA_ARGS__) +#define error(...) fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "%lu | %s\n", \ + g_asm_line_number, g_asm_line); #define MAX_LINE_LEN 256

@@ -36,19 +38,19 @@ uint32_t a_field = 0;

size_t i, a = 0; if (line[0] != '@') { - alert("error: A-type instruction doesn't start with @\n"); + error("syntax error: A-type instruction doesn't start with @\n"); return false; } if (line[1] == '\0') { - alert("error: A-type instruction empty after @\n"); + error("syntax error: A-type instruction empty after @\n"); return false; } for (i = 1; (c = line[i]) != '\0' && a < 6; ++i) { if ('0' <= c && c <= '9') { if (a > 4) { - alert("error: @<number> too long\n"); + error("error: @<number> too long\n"); return false; } a_field_str[a] = c; // get number

@@ -56,7 +58,7 @@ a++;

} else if ((c == ' ' || c == '\t' || c == '/') && i > 1) { break; } else { // any other character - alert("syntax error: invalid char '%c' found after @\n", + error("syntax error: invalid char '%c' found after @\n", c); return false; }

@@ -67,7 +69,7 @@

// TODO: extension: support negative numbers a_field = myatoi(a_field_str); if (a_field > 32767) { - alert("error: %u > 32767, too large\n", a_field); + error("error: %u > 32767, too large\n", a_field); return false; }

@@ -80,50 +82,41 @@ */

static bool parse_c_type_dest(const char *dest_line, uint8_t *dest) { size_t len; - char *err_dest_fmt = "syntax error: destination format incorrect\n"; DEBUG("dest_line: %s\n", dest_line); - for (len = 0; dest_line[len] != '='; ++len) {} // read until '=' - - if (len == 3) { - if (dest_line[0] == 'A' && dest_line[1] == 'D' && - dest_line[2] == 'M') { - *dest = 0x7; + for (len = 0; dest_line[len] != '='; ++len) { // read until '=' + if (dest_line[len] == 'A') { + if (*dest & 0x04) { // if A register already set + error("syntax error: A register set twice\n"); + return false; + } + *dest |= 0x04; + } else if (dest_line[len] == 'D') { + if (*dest & 0x02) { // if D register already set + error("syntax error: D register set twice\n"); + return false; + } + *dest |= 0x02; + } else if (dest_line[len] == 'M') { + if (*dest & 0x01) { // if M register already set + error("syntax error: M register set twice\n"); + return false; + } + *dest |= 0x01; } else { - alert("%s", err_dest_fmt); - alert("%lu | %s\n", g_asm_line_number, g_asm_line); + error("syntax error: invalid destination register %c\n", + dest_line[len]); return false; } - } else if (len == 2) { - if (dest_line[0] == 'D' && dest_line[1] == 'M') { - *dest = 0x3; - } else if (dest_line[0] == 'A' && dest_line[1] == 'M') { - *dest = 0x5; - } else if (dest_line[0] == 'A' && dest_line[1] == 'D') { - *dest = 0x6; - } else { - alert("%s", err_dest_fmt); - alert("%lu | %s\n", g_asm_line_number, g_asm_line); + + if (len >= 3) { + error("syntax error: dest field incorrect length %lu\n", + len); return false; } - } else if (len == 1) { - switch (dest_line[0]) { - case 'M': - *dest = 0x1; - break; - case 'D': - *dest = 0x2; - break; - case 'A': - *dest = 0x4; - break; - default: - alert("%s", err_dest_fmt); - alert("%lu | %s\n", g_asm_line_number, g_asm_line); - return false; - } - } else { - alert("syntax error: dest field incorrect length %lu\n", len); + } + if (len == 0) { + error("syntax error: dest field empty\n"); return false; }

@@ -151,7 +144,7 @@ case 'D': *comp = 0x0c; break; // 0 001100

case 'A': *comp = 0x30; break; // 0 110000 case 'M': *comp = 0x70; break; // 1 110000 default: - alert("syntax error: comp field incorrect value\n"); + error("syntax error: comp field incorrect value\n"); return false; } } else if (len == 2) { // -1 !D !A !M -D -A -M

@@ -162,7 +155,7 @@ case 'D': *comp = 0x0f; break; // 0 001111

case 'A': *comp = 0x33; break; // 0 110011 case 'M': *comp = 0x73; break; // 1 110011 default: - alert("syntax error: comp field incorrect value\n"); + error("syntax error: comp field incorrect value\n"); return false; } } else if (comp_line[0] == '!') {

@@ -171,11 +164,11 @@ case 'D': *comp = 0x0d; break; // 0 001101

case 'A': *comp = 0x31; break; // 0 110001 case 'M': *comp = 0x71; break; // 1 110001 default: - alert("syntax error: comp field incorrect value\n"); + error("syntax error: comp field incorrect value\n"); return false; } } else { - alert("syntax error: comp field incorrect value\n"); + error("syntax error: comp field incorrect value\n"); return false; } } else if (len == 3) {

@@ -186,7 +179,7 @@ *comp = 0x1f; // 0 011111

} else if (comp_line[1] == '-') { *comp = 0x0e; // 0 001110 } else { - alert("syntax error: comp field " + error("syntax error: comp field " "incorrect value\n"); return false; }

@@ -196,7 +189,7 @@ *comp = 0x40; // _1_ 000000

} else if (comp_line[2] == 'A') { *comp = 0x00; // _0_ 000000 } else { - alert("syntax error: comp field " + error("syntax error: comp field " "incorrect value\n"); return false; }

@@ -207,7 +200,7 @@ case '-': *comp |= 0x13; break; // 010011

case '&': *comp |= 0x00; break; // 000000 case '|': *comp |= 0x15; break; // 010101 default: - alert("syntax error: comp field " + error("syntax error: comp field " "incorrect value\n"); return false; }

@@ -219,7 +212,7 @@ *comp = 0x40; // _1_ 000000

} else if (comp_line[0] == 'A') { *comp = 0x00; // _0_ 000000 } else { - alert("syntax error: comp field incorrect value\n"); + error("syntax error: comp field incorrect value\n"); return false; }

@@ -230,16 +223,15 @@ *comp |= 0x32; // 1 110010

} else if (comp_line[1] == '-' && comp_line[2] == 'D') { *comp |= 0x07; // 1 000111 } else { - alert("syntax error: comp field incorrect value\n"); + error("syntax error: comp field incorrect value\n"); return false; } } } else { - alert("syntax error: comp field incorrect length %lu\n", len); + error("syntax error: comp field incorrect length %lu\n", len); return false; } - //*comp = 0x53; // STUB: 0b01010011 return true; }

@@ -258,7 +250,7 @@ jump_line[len] == 'Q' || jump_line[len] == 'L' ||

jump_line[len] == 'N' || jump_line[len] == 'M' || jump_line[len] == 'P'; ++len) {} if (len != 3) { - alert("syntax error: jump field incorrect length %lu\n", len); + error("syntax error: jump field incorrect length %lu\n", len); return false; }

@@ -270,14 +262,14 @@ *jump = 0x1;

} else if (jump_line[2] == 'E') { // if "JGE" *jump = 0x3; } else { - alert(err_3rd_char); return false; + error(err_3rd_char); return false; } break; case 'E': // if "JE_" if (jump_line[2] == 'Q') { // if "JEQ" *jump = 0x2; } else { - alert(err_3rd_char); return false; + error(err_3rd_char); return false; } break; case 'L': // if "JL_"

@@ -286,29 +278,29 @@ *jump = 0x4;

} else if (jump_line[2] == 'E') { // if "JLE" *jump = 0x6; } else { - alert(err_3rd_char); return false; + error(err_3rd_char); return false; } break; case 'N': // if "JN_" if (jump_line[2] == 'E') { // if "JNE" *jump = 0x5; } else { - alert(err_3rd_char); return false; + error(err_3rd_char); return false; } break; case 'M': // if "JM_" if (jump_line[2] == 'P') { // if "JMP" *jump = 0x7; } else { - alert(err_3rd_char); return false; + error(err_3rd_char); return false; } break; default: - alert(err_2nd_char); + error(err_2nd_char); return false; } } else { - alert(err_1st_char); + error(err_1st_char); return false; }

@@ -331,28 +323,27 @@ uint8_t dest = 0; // default value when not present

uint8_t comp = 0; uint8_t jump = 0; // default value when not present + // set pointers to comp, dest, and/or jump field (if applicable) c = line[0]; for (i = 0; c != ' ' && c != '\t' && - c != '\n' && c != '\0'; ++i) { + c != '\n' && c != '\0'; ++i) { // read until end of line c = line[i]; - if (c == '=') { + if (c == '=') { // indicates dest field if (1 <= i && i <= 3) { dest_start = &line[0]; // start of line // this 'i+1' might be dangerous! comp_start = &line[i+1]; // after "[dest]=" } else { - alert("syntax error: jump field incorrect " - "length\n"); + error("syntax error: dest incorrect length %lu\n", i); return false; } - } else if (c == ';') { + } else if (c == ';') { // indicates jump field if (1 <= i && i <= 7) { // this 'i+1' might be dangerous! jump_start = &line[i+1]; // after "[comp];" } else { - alert("syntax error: jump field incorrect" - " length\n"); + error("syntax error: jump incorrect length %lu\n", i); return false; } }

@@ -407,7 +398,7 @@ } else if (c >= '!' && c < '~') {

ret = parse_c_type(&line[i], instruction); break; } else { - alert("syntax error: line '%s' incorrectly formatted\n", + error("syntax error: line '%s' incorrectly formatted\n", line); }

@@ -444,7 +435,7 @@ continue;

} else if (slash_found) { // this char not slash, but previous was: invalid syntax // TODO: add line, column numbers - alert("syntax error: found '/', comments need '//'\n"); + error("syntax error: found '/', comments need '//'\n"); return false; } else { // non-whitespace/slash char discovered

@@ -471,14 +462,14 @@ char *in_file_path;

FILE *fp; if (argc != 2) { // requires 1 argument - alert(usage_msg); + fprintf(stderr, usage_msg); exit(-1); } in_file_path = argv[1]; fp = fopen(in_file_path, "r"); if (fp == NULL) { - alert("failed to open file for reading\n"); + fprintf(stderr, "failed to open file for reading\n"); exit(-1); }