G

G Programming Language
git clone http://git.omkov.net/G
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2022-01-25 12:42:02
Commit44d040093e5e4e9f401d0f1e676fd4802ecd2109
Parent092464359b4127320fbed1380200df5f90c3f8b9

parse: Add type parsing for decl's and proc's

Diffstat

M src/parse.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------

1 files changed, 102 insertions, 41 deletions

diff --git a/src/parse.c b/src/parse.c
index a577c95..81d8f1f 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -28,12 +28,12 @@ char *ast_ks[] = {
 
 static ast *parse_decl(lex *l, syt *st);
 
-static ast *parse_stmt(lex *l);
-static ast *parse_stmt_compound(lex *l);
+static ast *parse_stmt(lex *l, syt *st);
+static ast *parse_stmt_compound(lex *l, syt *st);
 
-static ast *parse_expr(lex *l);
+static ast *parse_expr(lex *l, syt *st);
 
-static ast *parse_proc(lex *l);
+static ast *parse_proc(lex *l, syt *st);
 
 static ast *parse_int(lex *l);
 
@@ -73,63 +73,88 @@ ast *parse(lex *l) {
 
 /* Parse a declaration. */
 static ast *parse_decl(lex *l, syt *st) {
+	/* Store the declaration's line, column, hash, and identifier */
 	sym sm = { SK_NULL, T.ln, T.cl, T.h, T.s };
 
 	lex_kind(l, LK_ID); lex_kind(l, LK_COLON);
 
-	if (T.k == LK_ID) { /* TODO lookup and store type */ }
-	if (T.k == LK_SCOLON) { error(1, "LK_SCOLON (parse_decl)"); }
-	
-	switch (T.k) {
-		case LK_COLON:  { lex_kind(l, LK_COLON);  } goto decl_expr;
-		case LK_ASSIGN: { lex_kind(l, LK_ASSIGN); } goto decl_expr;
-		decl_expr: {
-			sm.a = ast_aloc(); sm.a->k = AK_DECL; sm.a->s = strdup(sm.s);
-			ast_push(sm.a, parse_expr(l));
-		} break;
-		default: { error(
-			1, "%s:%zu:%zu: error: Unexpected: \"%s\" (parse_decl)",
-			l->n, lex_peek(l).ln + 1, lex_peek(l).cl + 1, tok_ks[lex_peek(l).k]
-		); } break;
+	/* Search for a store the declaration's type if specified */
+	if (T.k == LK_ID) {
+		sym s = syt_search_h(st, T.h, T.s);
+		
+		if (s.k == SK_NULL) { error( /* ERROR */
+			1, "%s:%zu:%zu: error: use of undeclared identifier \"%s\"",
+			l->n, T.ln + 1, T.cl + 1, T.s
+		); }
+		if (s.k != SK_TYPE) { error( /* ERROR */
+			1, "%s:%zu:%zu: error: expected type identifier",
+			l->n, T.ln + 1, T.cl + 1
+		); }
+		
+		sm.t = s.t; lex_next(l);
+		
+		if (T.k == LK_SCOLON) {
+			/* Allocate the AST and skip ahead */
+			lex_next(l); sm.a = ast_aloc(); sm.a->k = AK_DECL;
+			sm.a->s = strdup(sm.s); sm.k = SK_NASS; goto decl;
+		}
+	}
+	else if (T.k == LK_SCOLON) { error( /* ERROR */
+		1, "%s:%zu:%zu: error: a declaration without a type is invalid",
+		l->n, T.ln + 1, T.cl + 1
+	); }
+	
+	/* Assign a constant or variable value */
+	if (T.k == LK_COLON || T.k == LK_ASSIGN) {
+		lex_next(l); sm.a = ast_aloc(); sm.a->k = AK_DECL;
+		sm.a->s = strdup(sm.s); ast_push(sm.a, parse_expr(l, st));
+	}
+	else { error( /* ERROR */
+		1, "%s:%zu:%zu: error: expected ':' or '='",
+		l->n, T.ln + 1, T.cl + 1
+	); }
+	
+	switch (sm.a->c.a[0]->k) {
+	case AK_PROC: { sm.k = SK_PROC; } break;
+	// if (sm.a->c.a[0]->k == AK_PROC) { sm.a->c.a[0]->s = sm.a->s; }
+	default: { sm.k = SK_NASS; } break; /* TODO */
+	// default: { error( /* ERROR */
+	// 	1, "%s:%zu:%zu: error: unhandled AST kind \"%s\"",
+	// 	l->n, T.ln + 1, T.cl + 1, ast_ks[sm.a->k]
+	// ); } break;
 	}
 
-	if (sm.a->c.a[0]->k == AK_PROC) { sm.a->c.a[0]->s = sm.a->s; }
-	
-	assert(sm.h != 0);
+	decl:; assert(sm.h != 0);
 
 	/* Confirm that the identifier is not a keyword */
-	if (syt_lookup_h(&kwt, sm.h, sm.s).h != 0) {
-		error(
-			1, "%s:%zu:%zu: error: keyword '%s' (parse_decl)",
-			l->n, sm.ln + 1, sm.cl + 1, sm.s
-		);
-	}
+	if (syt_lookup_h(&kwt, sm.h, sm.s).k != SK_NULL) { error( /* ERROR */
+		1, "%s:%zu:%zu: error: redefinition of keyword \"%s\"",
+		l->n, sm.ln + 1, sm.cl + 1, sm.s
+	); }
 
 	/* Confirm that the identifier is not being reused */
-	if (syt_lookup_h(st, sm.h, sm.s).h != 0) {
-		error(
-			1, "%s:%zu:%zu: error: redefinition of '%s' (parse_decl)",
-			l->n, sm.ln + 1, sm.cl + 1, sm.s
-		);
-	}
+	if (syt_lookup_h(st, sm.h, sm.s).k != SK_NULL) { error( /* ERROR */
+		1, "%s:%zu:%zu: error: redefinition of identifier \"%s\"",
+		l->n, sm.ln + 1, sm.cl + 1, sm.s
+	); }
 
 	/* Otherwise insert the new symbol and return */
 	syt_insert_h(st, sm.h, sm.s, sm); return sm.a;
 }
 
 /* Parse a statement. */
-static ast *parse_stmt(lex *l) {
-	if (lex_peek(l).k == LK_LBRACE) { return parse_stmt_compound(l); }
+static ast *parse_stmt(lex *l, syt *st) {
+	if (T.k == LK_LBRACE) { return parse_stmt_compound(l, st); }
 
 	ast *a = ast_aloc();
 
-	switch (lex_peek(l).k) {
+	switch (T.k) {
 	case LK_RETURN: {
-		lex_kind(l, LK_RETURN); a->k = AK_RETURN; ast_push(a, parse_expr(l));
+		lex_kind(l, LK_RETURN); a->k = AK_RETURN; ast_push(a, parse_expr(l, st));
 	} break;
 	default: { error(
-		1, "%zu:%zu: Unexpected: \"%s\" (parse_stmt)",
-		lex_peek(l).ln + 1, lex_peek(l).cl + 1, tok_ks[lex_peek(l).k]
+		1, "%s:%zu:%zu: Unexpected: \"%s\" (parse_stmt)",
+		l->n, T.ln + 1, T.cl + 1, tok_ks[T.k]
 	); } break;
 	}
 
@@ -137,58 +162,62 @@ static ast *parse_stmt(lex *l) {
 }
 
 /* Parse a compound statement. */
-static ast *parse_stmt_compound(lex *l) {
+static ast *parse_stmt_compound(lex *l, syt *st) {
 	lex_kind(l, LK_LBRACE);
 
 	ast *a = ast_aloc(); a->k = AK_COMP; syt_init(&a->st);
 
 	/* Parse statements until EOF or closing brace */
-	for (; lex_peek(l).k != LK_EOF && lex_peek(l).k != LK_RBRACE;) {
-		ast_push(a, parse_stmt(l));
+	for (; T.k != LK_EOF && T.k != LK_RBRACE;) {
+		ast_push(a, parse_stmt(l, &a->st));
 	}
 
 	lex_kind(l, LK_RBRACE); return a;
 }
 
 /* Parse an expression. */
-static ast *parse_expr(lex *l) {
-	ast *a = ast_aloc();
-	
-	switch (lex_peek(l).k) {
-	case LK_PROC: { return parse_proc(l); } break;
+static ast *parse_expr(lex *l, syt *st) {
+	switch (T.k) {
+	case LK_PROC: { return parse_proc(l, st); } break;
 	case LK_INT: { return parse_int(l); } break;
 	default: { error(
-		1, "%zu:%zu: Unexpected: \"%s\" (parse_expr)",
-		lex_peek(l).ln + 1, lex_peek(l).cl + 1, tok_ks[lex_peek(l).k]
+		1, "%s:%zu:%zu: Unexpected: \"%s\" (parse_expr)",
+		l->n, T.ln + 1, T.cl + 1, tok_ks[T.k]
 	); } break;
 	}
-	
-	return a;
 }
 
 /* Parse a procedure. */
-static ast *parse_proc(lex *l) {
+static ast *parse_proc(lex *l, syt *st) {
 	lex_kind(l, LK_PROC); lex_kind(l, LK_LPAREN);
 	ast *a = ast_aloc(); a->k = AK_PROC;
 
 	/* Parse optional procedure parameter(s) */
 	/* TODO parse parameters(s) */
-	if (lex_peek(l).k != LK_RPAREN) {
-		error(1, "UNIMPLEMENTED (parse_proc)");
-	}
-	
 	lex_kind(l, LK_RPAREN);
 
 	/* Parse optional procedure return type(s) */
 	/* TODO parse more than one unnamed return type */
-	if (lex_peek(l).k == LK_RARROW) {
-		lex_kind(l, LK_RARROW);
+	if (T.k == LK_RARROW) {
+		lex_next(l); tok t = lex_kind(l, LK_ID);
+		sym s = syt_search_h(st, t.h, t.s);
+		
+		/* Confirm that the return type exists */
+		if (s.k == SK_NULL) { error( /* ERROR */
+			1, "%s:%zu:%zu: error: undefined identifier \"%s\"",
+			l->n, T.ln + 1, T.cl + 1, t.s
+		); }
+		
+		/* Confirm that the return type is a type */
+		if (s.k != SK_TYPE) { error( /* ERROR */
+			1, "%s:%zu:%zu: error: expected a type",
+			l->n, T.ln + 1, T.cl + 1
+		); }
 
-		/* TODO dont hardcode return type */
-		lex_kind(l, LK_ID); a->t = &TYPE(TY_S64);
+		a->t = s.t;
 	}
 
-	ast_push(a, parse_stmt_compound(l)); return a;
+	ast_push(a, parse_stmt_compound(l, st)); return a;
 }
 
 static ast *parse_int(lex *l) {
@@ -199,7 +228,9 @@ static ast *parse_int(lex *l) {
 
 void ast_print(ast *a, UINT i) {
 	for (UINT j = 0; j != i; ++j) { printf("    "); }
-	printf("%zu:%zu: %s: %s\n", a->ln, a->cl, ast_ks[a->k], a->s);
+	printf("%zu:%zu: %s: %s", a->ln, a->cl, ast_ks[a->k], a->s);
+	if (a->k == AK_PROC) { printf(" -> %s", a->t->s); }
+	fputc('\n', stdout);
 
 	if (a->c.a != NULL) for (UINT ci = 0; ci != a->c.al; ci += 1) {
 		ast_print(a->c.a[ci], i + 1);