summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-06-09 20:54:34 +0200
committerkdx <kikoodx@paranoici.org>2023-06-09 21:08:17 +0200
commitb1ecaf35206e901309ed058c61b5ec20afc94ca0 (patch)
tree3d3845d13b7c6387dd2c14e2c1d8783a523af381
parentcfc5d381a00fdbd812396c3c4e67616cfa669223 (diff)
downloadgolem-b1ecaf35206e901309ed058c61b5ec20afc94ca0.tar.gz
parse function
-rw-r--r--src/main.c84
-rwxr-xr-xtesting.sh8
2 files changed, 78 insertions, 14 deletions
diff --git a/src/main.c b/src/main.c
index 8c75915..0bfa197 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
diff --git a/testing.sh b/testing.sh
index 7abae1d..467d899 100755
--- a/testing.sh
+++ b/testing.sh
@@ -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.*