diff options
author | kdx <kikoodx@paranoici.org> | 2023-06-09 20:54:34 +0200 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2023-06-09 21:08:17 +0200 |
commit | b1ecaf35206e901309ed058c61b5ec20afc94ca0 (patch) | |
tree | 3d3845d13b7c6387dd2c14e2c1d8783a523af381 | |
parent | cfc5d381a00fdbd812396c3c4e67616cfa669223 (diff) | |
download | golem-b1ecaf35206e901309ed058c61b5ec20afc94ca0.tar.gz |
parse function
-rw-r--r-- | src/main.c | 84 | ||||
-rwxr-xr-x | testing.sh | 8 |
2 files changed, 78 insertions, 14 deletions
@@ -57,7 +57,7 @@ static Token * skip(Token *tok, char *s) { if (!equal(tok, s)) - error("expected '%s'", s); + error("expected '%s'; got '%.*s'", s, tok->len, tok->loc); return tok->next; } @@ -86,7 +86,7 @@ is_punct(const char *p) if (strchr("=!<>", p[0]) != NULL && p[1] == '=') return 2; - return (strchr("+-/*()<>;", p[0]) != NULL); + return (strchr("+-/*()<>,;{}", p[0]) != NULL); } static Token * @@ -111,7 +111,7 @@ tokenize(char *p) if (*p == '\'' && p[1] != '\0' && p[2] == '\'') { cur = cur->next = new_token(TOK_NUM, p, p + 3); - cur->val = (unsigned char)*p; + cur->val = (unsigned char)p[1]; p += 3; continue; } @@ -125,7 +125,7 @@ tokenize(char *p) if (isalpha(*p)) { char *q = p; - while (isalnum(*p)) + while (isalnum(*p) || *p == '_') p += 1; cur = cur->next = new_token(TOK_WORD, q, p); continue; @@ -149,7 +149,8 @@ typedef enum { NOD_LE, // <= NOD_NUM, // integer NOD_EXPR_STMT, - NOD_FUN_STMT, + NOD_FUN, + NOD_WORD, } NodeType; typedef struct Node Node; @@ -159,6 +160,8 @@ struct Node { Node *rhs; Node *next; int val; + char *loc; + int len; }; static Node * @@ -172,6 +175,17 @@ new_node(NodeType type) } static Node * +new_word(Token *tok) +{ + expect(tok, TOK_WORD); + + Node *const node = new_node(NOD_WORD); + node->loc = tok->loc; + node->len = tok->len; + return node; +} + +static Node * new_binary(NodeType type, Node *lhs, Node *rhs) { Node *const node = new_node(type); @@ -194,6 +208,8 @@ new_num(int val) return node; } +static Node *stmt(Token **rest, Token *tok); +static Node *function(Token **rest, Token *tok); static Node *expr(Token **rest, Token *tok); static Node *expr_stmt(Token **rest, Token *tok); static Node *equality(Token **rest, Token *tok); @@ -202,8 +218,41 @@ static Node *add(Token **rest, Token *tok); static Node *mul(Token **rest, Token *tok); static Node *primary(Token **rest, Token *tok); -static Node -*expr(Token **rest, Token *tok) +static Node * +function(Token **rest, Token *tok) +{ + Node *const node = new_node(NOD_FUN); + + tok = skip(tok, "fn"); + + node->lhs = new_word(tok); + tok = skip(tok->next, "("); + + Node head = {0}; + Node *cur = &head; + while (tok->type == TOK_WORD) { + cur = cur->next = new_word(tok); + tok = tok->next; + if (equal(tok, ",")) + tok = tok->next; + } + node->lhs->next = cur; + tok = skip(tok, ")"); + tok = skip(tok, "{"); + + cur = &head; + while (tok->type != TOK_EOF && !equal(tok, "}")) + cur = cur->next = stmt(&tok, tok); + tok = skip(tok, "}"); + + node->rhs = head.next; + + *rest = tok; + return node; +} + +static Node * +expr(Token **rest, Token *tok) { return equality(rest, tok); } @@ -387,8 +436,11 @@ gen_expr(Node *node) } static void -codegen(Node *node) +gen_function(Node *node) { + printf("@_fn_%.*s\n", node->lhs->len, node->lhs->loc); + + node = node->rhs; while (node != NULL) { gen_expr(node->lhs); while (depth) { @@ -397,6 +449,17 @@ codegen(Node *node) } node = node->next; } + + printf("\tLIT 0000 ( default return )\n\tRET\n"); +} + +static void +codegen(Node *node) +{ + while (node != NULL) { + gen_function(node); + node = node->next; + } } // program = stmt* @@ -406,7 +469,7 @@ parse(Token *tok) Node head = {0}; Node *cur = &head; while (tok->type != TOK_EOF) - cur = cur->next = stmt(&tok, tok); + cur = cur->next = function(&tok, tok); return head.next; } @@ -420,9 +483,8 @@ main(int argc, char **argv) Node *node = parse(tok); - printf("\tJMP ,main\n"); + printf("\tJMP ,_fn_main ( entry point )\n"); codegen(node); - printf("\tRET\n"); assert(depth == 0); return 0; @@ -4,12 +4,14 @@ function test() { CODE="$1" echo "--- $CODE ---" ./build/golem "$CODE" >"build/tmp.orgaasm" + cat "build/tmp.orgaasm" orgaasm "build/tmp.orgaasm" "build/tmp.rom" orgaemu "build/tmp.rom" + echo "" } tup || exit 1 -test "5 + 2;" -test "6 + 3;" -test "'a' - 'b';" +test "fn main(){5 + 2;}" +test "fn main(){6 + 3;}" +test "fn main(){'a' - 'b';}" rm -f build/tmp.* |