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:
M | main.c | | | 128 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
A | prog.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