|
@@ -29,6 +29,9 @@ static ast_node_t *parse_fn_proto(token_t *ts);
|
|
|
static ast_node_t *parse_fn_params(token_t *ts);
|
|
|
static ast_node_t *parse_call(token_t *ts);
|
|
|
static ast_node_t *parse_var(token_t *ts);
|
|
|
+static void emit_node(ast_node_list_t *nl, ast_node_t *node);
|
|
|
+static void dump_node(ast_node_t *node);
|
|
|
+static void dump_nodes(ast_node_list_t *nl);
|
|
|
static token_t *peek(token_t *ts);
|
|
|
static token_t *eat(token_t *ts);
|
|
|
|
|
@@ -60,6 +63,51 @@ static ast_type_t get_type(char *name)
|
|
|
return UNKNOWN;
|
|
|
}
|
|
|
|
|
|
+static ast_op_t get_operator(token_t *token)
|
|
|
+{
|
|
|
+ switch (token->type) {
|
|
|
+ case TOKEN_PLUS:
|
|
|
+ return OP_PLUS;
|
|
|
+ case TOKEN_MIN:
|
|
|
+ return OP_MIN;
|
|
|
+ case TOKEN_SLASH:
|
|
|
+ return OP_DIV;
|
|
|
+ case TOKEN_STAR:
|
|
|
+ return OP_MUL;
|
|
|
+ case TOKEN_MOD:
|
|
|
+ return OP_MOD;
|
|
|
+ case TOKEN_AND:
|
|
|
+ return OP_AND;
|
|
|
+ case TOKEN_OR:
|
|
|
+ return OP_OR;
|
|
|
+ case TOKEN_BANG:
|
|
|
+ return OP_NOT;
|
|
|
+ case TOKEN_NOT_EQ:
|
|
|
+ return OP_NOT_EQ;
|
|
|
+ case TOKEN_EQ_EQ:
|
|
|
+ return OP_EQ;
|
|
|
+ case TOKEN_GT:
|
|
|
+ return OP_GT;
|
|
|
+ case TOKEN_GT_EQ:
|
|
|
+ return OP_GT_EQ;
|
|
|
+ case TOKEN_LT:
|
|
|
+ return OP_GT;
|
|
|
+ case TOKEN_LT_EQ:
|
|
|
+ return OP_GT_EQ;
|
|
|
+ case TOKEN_B_OR:
|
|
|
+ return OP_BIN_OR;
|
|
|
+ case TOKEN_B_XOR:
|
|
|
+ return OP_BIN_XOR;
|
|
|
+ case TOKEN_B_AND:
|
|
|
+ return OP_BIN_AND;
|
|
|
+ case TOKEN_B_NOT:
|
|
|
+ return OP_BIN_NOT;
|
|
|
+ default:
|
|
|
+ file_fatal_error("invalid operator '%s' on line %zu\n",
|
|
|
+ token->value, token->line_n);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static ast_node_t *parse_expr(token_t *ts)
|
|
|
{
|
|
|
switch (ts->type) {
|
|
@@ -69,7 +117,10 @@ static ast_node_t *parse_expr(token_t *ts)
|
|
|
return parse_var(ts);
|
|
|
case TOKEN_IDENT:
|
|
|
return parse_id(ts);
|
|
|
+ case TOKEN_IMPORT:
|
|
|
+ /* TODO: parse import */
|
|
|
default:
|
|
|
+ return NULL;
|
|
|
file_fatal_error("unexpected token '%s' on line %zu\n",
|
|
|
ts->value, ts->line_n);
|
|
|
}
|
|
@@ -79,13 +130,17 @@ static ast_node_t *parse_expr(token_t *ts)
|
|
|
|
|
|
int parse_token_stream(token_t *ts)
|
|
|
{
|
|
|
+ ast_node_list_t *nl = smalloc(sizeof(ast_node_list_t));
|
|
|
+
|
|
|
verbose_printf("generating abstract syntax tree\n");
|
|
|
|
|
|
do {
|
|
|
- parse_expr(ts);
|
|
|
+ emit_node(nl, parse_expr(ts));
|
|
|
eat(ts);
|
|
|
} while(ts->type != TOKEN_EOF);
|
|
|
|
|
|
+ dump_nodes(nl);
|
|
|
+
|
|
|
return ERUPT_OK;
|
|
|
}
|
|
|
|
|
@@ -95,6 +150,7 @@ static ast_node_t *parse_fn(token_t *ts)
|
|
|
|
|
|
if (ts->type == TOKEN_SEMI_COLON) {
|
|
|
eat(ts);
|
|
|
+ return prototype;
|
|
|
} else if (ts->type == TOKEN_L_BRACE) {
|
|
|
/* TODO: parse block */
|
|
|
} else {
|
|
@@ -120,7 +176,7 @@ static ast_node_t *parse_fn_proto(token_t *ts)
|
|
|
ast_var_t **args = NULL;
|
|
|
size_t arg_count = 0;
|
|
|
|
|
|
- /* skip over function declaration token */
|
|
|
+ /* eat function declaration token */
|
|
|
eat(ts);
|
|
|
|
|
|
if (ts->type != TOKEN_IDENT)
|
|
@@ -130,7 +186,7 @@ static ast_node_t *parse_fn_proto(token_t *ts)
|
|
|
name = ts->value;
|
|
|
|
|
|
if (eat(ts)->type != TOKEN_L_PAREN)
|
|
|
- file_fatal_error("expecting (, got '%s' on line %zu\n",
|
|
|
+ file_fatal_error("expected (, got '%s' on line %zu\n",
|
|
|
ts->value, ts->line_n);
|
|
|
|
|
|
if (peek(ts)->type == TOKEN_R_PAREN) {
|
|
@@ -150,7 +206,7 @@ static ast_node_t *parse_fn_proto(token_t *ts)
|
|
|
ts->value, ts->line_n, name);
|
|
|
}
|
|
|
|
|
|
- /* skip over ) or type declaration token */
|
|
|
+ /* eat the ) or type declaration token */
|
|
|
eat(ts);
|
|
|
|
|
|
return create_fn_proto(name, args, arg_count, data_type);
|
|
@@ -201,16 +257,72 @@ static ast_node_t *parse_var(token_t *ts)
|
|
|
|
|
|
eat(ts);
|
|
|
|
|
|
- if (ts->type != TOKEN_EQ || ts->type != TOKEN_SEMI_COLON)
|
|
|
- file_fatal_error("expected assignment or semi-colon, got %s on line %zu\n",
|
|
|
- ts->value, ts->line_n);
|
|
|
+ if (ts->type != TOKEN_EQ && ts->type != TOKEN_SEMI_COLON)
|
|
|
+ file_fatal_error("expecting assignment or declaration, got '%s' on line %zu\n",
|
|
|
+ ts->value, ts->line_n);
|
|
|
+
|
|
|
+ if (ts->type == TOKEN_EQ) {
|
|
|
+ /* get to the value */
|
|
|
+ eat(ts);
|
|
|
+
|
|
|
+ if (peek(ts)->type == TOKEN_SEMI_COLON) {
|
|
|
+ value = ts->value;
|
|
|
+ } else {
|
|
|
+ /* TODO: parse expression */
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- /* declaration */
|
|
|
- if (ts->type == TOKEN_SEMI_COLON)
|
|
|
- return create_var_expr(name, type, value, mutable);
|
|
|
+ return create_var(name, type, value, mutable);
|
|
|
+}
|
|
|
+
|
|
|
+static void emit_node(ast_node_list_t *nl, ast_node_t *node)
|
|
|
+{
|
|
|
+ if (nl->node == NULL) {
|
|
|
+ nl->node = node;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (nl->next != NULL)
|
|
|
+ nl = nl->next;
|
|
|
+
|
|
|
+ nl->next = smalloc(sizeof(ast_node_list_t));
|
|
|
+ nl->next->node = node;
|
|
|
+ nl->next->next = NULL;
|
|
|
+}
|
|
|
|
|
|
- /* assignment */
|
|
|
+static void dump_node(ast_node_t *node)
|
|
|
+{
|
|
|
+ switch (node->type) {
|
|
|
+ case TYPE_VAR:
|
|
|
+ printf("variable:\n\tname: %s\n\ttype: %u\n\tmutable:%d\n",
|
|
|
+ node->var.name, node->var.data_type, node->var.mutable);
|
|
|
+ break;
|
|
|
+ case TYPE_PROTO:
|
|
|
+ printf("proto:\n\tname: %s\n\ttype: %u\n",
|
|
|
+ node->prototype.name, node->prototype.data_type);
|
|
|
+ break;
|
|
|
+ case TYPE_FN:
|
|
|
+ printf("function:\n");
|
|
|
+ dump_node(node->fn.prototype);
|
|
|
+ break;
|
|
|
+ case TYPE_CALL:
|
|
|
+ /* TODO */
|
|
|
+ break;
|
|
|
+ case TYPE_IF:
|
|
|
+ /* TODO */
|
|
|
+ break;
|
|
|
+ case TYPE_BIN_EXP:
|
|
|
+ /* TODO */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+static void dump_nodes(ast_node_list_t *nl)
|
|
|
+{
|
|
|
+ do {
|
|
|
+ dump_node(nl->node);
|
|
|
+ nl = nl->next;
|
|
|
+ } while (nl->next != NULL);
|
|
|
}
|
|
|
|
|
|
static token_t *peek(token_t *ts)
|