G

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

AuthorJakob Wakeling <[email protected]>
Date2022-03-28 02:26:44
Commitd47751def35f23c73f6722584cf0cf4934db9e36
Parentaf7cced8bd1c8b0e4115d10b679876174792068f

parse: Implement if and for statement parsing

Diffstat

M src/parse.c | 40 ++++++++++++++++++++++++++++++----------
M src/parse.h | 3 +--

2 files changed, 31 insertions, 12 deletions

diff --git a/src/parse.c b/src/parse.c
index 313d6e2..3555ea4 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -43,14 +43,14 @@ ast *ast_init(void) {
 	ast *a = calloc(1, sizeof (ast));
 	if (!a) { error(1, SERR); } return a;
 }
-// void ast_free(ast *a) {}
 
 /* Push a child AST node to an AST node. */
-s32 ast_push(ast *a, ast *c) {
+void ast_push(ast *a, ast *c) {
 	ast **ca = realloc(a->c.a, (a->c.al += 1) * sizeof (ast *));
 	if (!ca) { error(1, SERR); } else { a->c.a = ca; ca = NULL; }
 
-	a->c.a[a->c.al - 1] = c; return 0;
+	/* Store pointer from parent to child and vice versa */
+	c->p = a; a->c.a[a->c.al - 1] = c;
 }
 
 #define T (l->t) /* lex_peek equivalent */
@@ -124,9 +124,6 @@ static ast *parse_stmt_decl(lex *l, syt *st) {
 	if (T.k == TK_COLON || T.k == TK_ASSIGN) { lex_next(l); ast_push(sm.a, parse_expr(l, st)); }
 	else { error(1, "%s:%zu:%zu: error: expected ':' or '='", l->n, T.ln + 1, T.cl + 1); }
 
-	/* Store the parent AST node in the child */
-	sm.a->c.a[0]->p = sm.a;
-	
 	/* Parse a semicolon if one is required */
 	if (sm.a->c.a[0]->k != AK_PROC) { lex_kind(l, TK_SCOLON); }
 
@@ -136,7 +133,7 @@ static ast *parse_stmt_decl(lex *l, syt *st) {
 
 /* Parse an expression statement. */
 static ast *parse_stmt_expr(lex *l, syt *st) {
-	ast *a; if (T.k != TK_SCOLON) { a = parse_expr(l, st); }
+	ast *a = NULL; if (T.k != TK_SCOLON) { a = parse_expr(l, st); }
 	lex_kind(l, TK_SCOLON); return a;
 }
 
@@ -151,10 +148,30 @@ static ast *parse_stmt_return(lex *l, syt *st) {
 }
 
 /* Parse an if statement. */
-static ast *parse_stmt_if(lex *l, syt *st) { /* TODO */ }
+static ast *parse_stmt_if(lex *l, syt *st) {
+	lex_kind(l, TK_IF); lex_kind(l, TK_LPAREN);
+	ast *a = ast_init(); a->k = AK_IF;
+	
+	/* Parse expression and closing parenthesis */
+	ast_push(a, parse_expr(l, st)); lex_kind(l, TK_RPAREN);
+	
+	/* Parse the if statement body */
+	ast_push(a, parse_stmt(l, st)); return a;
+}
 
 /* Parse a for statement. */
-static ast *parse_stmt_for(lex *l, syt *st) { /* TODO */ }
+static ast *parse_stmt_for(lex *l, syt *st) {
+	lex_kind(l, TK_FOR); lex_kind(l, TK_LPAREN);
+	ast *a = ast_init(); a->k = AK_FOR;
+	
+	/* Parse one to three expressions and a closing parenthesis */
+	ast_push(a, parse_stmt_expr(l, st));
+	ast_push(a, parse_stmt_expr(l, st));
+	ast_push(a, parse_expr(l, st)); lex_kind(l, TK_RPAREN);
+	
+	/* Parse the for statement body */
+	ast_push(a, parse_stmt(l, st)); return a;
+}
 
 /* Parse an expression. */
 static ast *parse_expr(lex *l, syt *st) {
@@ -206,7 +223,7 @@ static ast *parse_int(lex *l) {
 /* Recursively print an AST. */
 void ast_print(ast *a, UINT i) {
 	for (UINT j = 0; j != i; ++j) { printf("    "); }
-	printf("%zu:%zu: %s: %s", a->ln, a->cl, ast_ks[a->k], a->s);
+	printf("%zu:%zu: %s: %s", a->ln + 1, a->cl + 1, ast_ks[a->k], a->s);
 	if (a->k == AK_PROC) { printf(" -> %s", a->t->s); }
 	fputc('\n', stdout);
 
diff --git a/src/parse.h b/src/parse.h
index 11fe029..67eaab7 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -32,8 +32,7 @@ typedef struct ast_s {
 extern char *ast_ks[];
 
 extern ast *ast_init(void);
-extern void ast_free(ast *a);
-extern s32  ast_push(ast *a, ast *c);
+extern void ast_push(ast *a, ast *c);
 
 extern ast *parse(lex *l);