nooc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit c0ce468e1f980dd5bd183993e9582dc8ff66c3a1
parent 3a3956f653887587656dcbe74304547d69392bdf
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Mon,  1 Nov 2021 23:48:43 -0500

add simple lexing, parsing and codegen capable of "compiling" prog.nc

Diffstat:
Mmain.c | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Aprog.nc | 2++
2 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/main.c b/main.c @@ -1,3 +1,4 @@ +#include <ctype.h> #include <elf.h> #include <fcntl.h> #include <string.h> @@ -7,7 +8,7 @@ #include <sys/mman.h> #include <unistd.h> -char code[] = {0xb8, 60, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xf, 0x5}; +char code[] = {0xb8, 0, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xf, 0x5}; int elf(char *text, size_t len, FILE *f) @@ -69,9 +70,120 @@ elf(char *text, size_t len, FILE *f) fwrite(text, 1, len, f); } +enum tokentype { + TOK_EXIT = 1, + TOK_LPAREN, + TOK_RPAREN, + TOK_NUM, +}; + +struct slice { + char *ptr; + size_t len; +}; + +struct token { + enum tokentype type; + struct slice slice; + struct token *next; +}; + +struct token * +lex(struct slice start) +{ + struct token *head = calloc(1, sizeof(struct token)); + if (!head) + return NULL; + + struct token *cur = head; + while (start.len) { + if (strncmp(start.ptr, "exit", sizeof("exit") - 1) == 0) { + cur->type = TOK_EXIT; + start.ptr += 4; + start.len -= 4; + } else if (*start.ptr == '(') { + cur->type = TOK_LPAREN; + start.ptr += 1; + start.len -= 1; + } else if (*start.ptr == ')') { + cur->type = TOK_RPAREN; + start.ptr += 1; + start.len -= 1; + } else if (isdigit(*start.ptr)) { + cur->slice.ptr = start.ptr; + cur->slice.len = 1; + start.ptr++; + start.len--; + cur->type = TOK_NUM; + while (isdigit(*start.ptr)) { + start.ptr++; + start.len--; + cur->slice.len++; + } + } + + cur->next = calloc(1, sizeof(struct token)); + + // FIXME: handle this properly + if (!cur->next) + return NULL; + + cur = cur->next; + } + + return head; +} + +enum func { + FUNC_NONE, + FUNC_EXIT +}; + +struct fcall { + enum func func; + int val; +}; + +void +error(char *error) +{ + fprintf(stderr, "%s\n", error); + exit(1); +} + +void +expect(struct token *tok, enum tokentype type) +{ + if (!tok) + error("unexpected null token!"); + if (tok->type != type) + error("mismatch"); +} + +struct fcall +parse(struct token *tok) +{ + struct fcall fcall; + expect(tok, TOK_EXIT); + + fcall.func = FUNC_EXIT; + tok = tok->next; + expect(tok, TOK_LPAREN); + tok = tok->next; + expect(tok, TOK_NUM); + + // FIXME: error check + fcall.val = strtol(tok->slice.ptr, NULL, 10); + tok = tok->next; + expect(tok, TOK_RPAREN); + tok = tok->next; + return fcall; +} + struct stat statbuf; -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { if (argc < 3) return 1; @@ -91,12 +203,18 @@ int main(int argc, char *argv[]) char *addr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, in, 0); close(in); - long val = strtol(addr, NULL, 10); + struct token *head = lex((struct slice){addr, statbuf.st_size}); + struct fcall fcall = parse(head); + munmap(addr, statbuf.st_size); - code[6] = val; + switch (fcall.func) { + case FUNC_EXIT: + code[1] = 60; + code[6] = fcall.val; + } - FILE *out = fopen(argv[2], "r"); + FILE *out = fopen(argv[2], "w"); if (!out) { close(in); fprintf(stderr, "couldn't open output\n"); diff --git a/prog.nc b/prog.nc @@ -0,0 +1 @@ +exit(12)+ \ No newline at end of file