Add basic line parser, Makefile, fix binary helper
x1phosura x1phosura@x1phosura.zone
Thu, 06 Oct 2022 00:47:17 -0700
6 files changed,
190 insertions(+),
31 deletions(-)
M
.gitignore
→
.gitignore
@@ -3,6 +3,8 @@ *.cmp
*.tst *.out -# ignore machine code files in project 05 +# ignore prokect 05 machine code files, project 06 test files, build artifacts projects/05/*.hack +projects/06/bin/* +projects/06/test/*
A
projects/06/Makefile
@@ -0,0 +1,18 @@
+ +CFLAGS = -std=c99 -Wall -Wextra + +all: bin/assembler1 +#all: bin/assembler1 bin/bin2text + +# TODO: clean up, make more Makefile-idiomatic + +bin/assembler1: assembler1/assembler1.c + $(CC) $(CFLAGS) -o $@ $< + +#bin/bin2text: bin2text.c +# $(CC) $(CFLAGS) -o $@ $< + +clean: + rm -vf bin/* + +.PHONY: clean
A
projects/06/assembler1/assembler1.c
@@ -0,0 +1,148 @@
+#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../bindump.h" + +#define DEBUG(x) printf(x) + +void die(const char *err_msg, int exit_val) +{ + perror(err_msg); + exit(exit_val); +} + +void alert(const char *err_msg) +{ + fprintf(stderr, "%s", err_msg); +} + +/* +uint16_t parse_a_type(const char *line) +{ + // eventually, if error, die("error: TODO explain...\n", -1); + DEBUG("parse_a_type()\n"); + return 0x0000; // STUB, A-type MSB == 0 anyway +} + +uint16_t parse_c_type(const char *line) +{ + DEBUG("parse_c_type()\n"); + return 0x8000; // STUB, C-type MSB == 1 anyway +} + +// does not care about line line length; exits at first newline or after +// relevant portion parsed (allows for syntactically-incorrect lines, I know) +uint16_t parse_instruction_w_type(const char *line, uint16_t *instruction) +{ + char c; + size_t i = 0; + + while ((c = line[i]) != '\n') { + if (c == ' ' || c == '\t') + ; // skip whitespace + else if (c == '@') { + instruction = parse_a_type(line); + break; + } else if (c >= '!' && c < '~') { + instruction = parse_c_type(line); + break; + } else { + die("error: TODO explain...\n", -1); + } + + ++i; + } + + ld.line_parsed = true; + return ld; +} +*/ + +bool parse_next_instruction(const char *line, uint16_t *instruction) +{ + *instruction = 1337; // STUB, should be 0x539, 0b0000010100111001 + + return true; +} + +/* return false for comment or invalid assembly instruction */ +bool parse_line(const char *line, size_t line_len, uint16_t *instruction) +{ + char c; + bool slash_found = false; + size_t i; + + if (line_len == 0 || line_len == 1) + return false; + + // filter out comment lines + //for (i = 0; (c = line[i]) != NULL; ++i) { + for (i = 0; i < line_len; ++i) { + c = line[i]; + + if (c == ' ' || c == '\t') { + continue; + } else if (c == '/') { + if (slash_found) { + // second slash means this is a comment + return false; + } + slash_found= true; + continue; + } else if (slash_found) { + // this char not slash, but previous was: invalid syntax + // TODO: add line, column numbers + alert("\tsyntax error: found '/', comments " + "need '//'\n"); + return false; + } else { + // non-whitespace/slash char discovered + break; + } + } + + // comment not found, so attempting to parse instruction + return parse_next_instruction(line, instruction); +} + +const char *test_lines[8] = {"// this is a comment\n", + "@12345\n", + "\n", + "M+1\n", + "@98\n", + "// this is another comment\n", + "/ this is a broken comment\n", + "D=M;JNE\n"}; +size_t test_lines_len = 8; // TODO calculate + +int main() +{ + // TODO: read file by lines, parse instructions + bool result = false; + uint16_t instruction; + size_t test_line_len; + + // New organization allows code to eventually work with lines fetched + // from a 'fgets()' loop or something + + // for testing + for (size_t i = 0; i < test_lines_len; ++i) { + printf("testing %lu: line to assemble: %s", i, test_lines[i]); + test_line_len = strlen(test_lines[i]); + result = parse_line(test_lines[i], test_line_len, &instruction); + if (result) { + printf("instruction: 0x%x | ", instruction); + bindump_word16(instruction); // output instruction as binary + putchar('\n'); + } + /* else { + printf("\tcomment or invalid syntax encountered\n"); + }*/ + } + + return 0; +} +
D
projects/06/bin2text.c
@@ -1,30 +0,0 @@
-#include <stdio.h> -#include <stdint.h> - -void output_binary(uint8_t b) -{ - char i, msb; - - for (i = 0; i < 8; ++i) { - msb = b & 0x80; - if (msb) - putchar('1'); - else - putchar('0'); - b <<= 1; - } -} - -int main(int argc, char *argv[]) -{ - char c, next_line = 0; - - while ((c = getchar()) != EOF) { - output_binary(c); - ++next_line; - if (next_line % 2 == 0) - putchar('\n'); - } - - return 0; -}
A
projects/06/bindump.h
@@ -0,0 +1,21 @@
+#include <stdio.h> +#include <stdint.h> + +void bindump_word16(uint16_t w) +{ + unsigned char i, msb; + char binary_string[17]; + binary_string[16] = '\0'; + + for (i = 0; i < 16; ++i) { + msb = (char)(w >> 15); + + if (msb != 0) + binary_string[i] = '1'; + else + binary_string[i] = '0'; + w <<= 1; + } + printf("%s", binary_string); +} +