G

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

AuthorJakob Wakeling <[email protected]>
Date2022-04-19 08:03:53
Commit38468186153fa035ab9a2fcafaa533175e3f9a33
Parentc2c12178e8195a0c613d25d12c276bd9dc385557

Handle unary operators with op_lookup

Diffstat

M src/parse.c | 63 ++++++++++++++++++++++++++++++++++++++++-----------------------
M src/parse.h | 1 +

2 files changed, 41 insertions, 23 deletions

diff --git a/src/parse.c b/src/parse.c
index 903d5e2..383844b 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -15,11 +15,14 @@
 #include <stdlib.h>
 #include <string.h>
 
+typedef struct { tok_k tk; ast_k ak; s32 o; bool as; } op;
+
 char *ast_ks[] = {
 	"AK_NULL", "AK_PROG", "AK_PROC", "AK_TYPE",
 
 	"AK_STMT", "AK_COMP", "AK_DECL", "AK_RETURN", "AK_IF", "AK_FOR",
 
+	"AK_OP_POS", "AK_OP_NEG",
 	"AK_OP_ADD", "AK_OP_SUB", "AK_OP_MUL", "AK_OP_DIV", "AK_OP_MOD",
 
 	"AK_VAR", "AK_INT",
@@ -38,6 +41,8 @@ static ast *parse_expr_proc(lex *l, syt *st);
 
 static ast *parse_int(lex *l, syt *st);
 
+static op op_lookup(tok_k tk, bool unary);
+
 /* Initialise an AST node. */
 ast *ast_init(void) {
 	ast *a = calloc(1, sizeof (ast));
@@ -183,22 +188,6 @@ static ast *parse_stmt_for(lex *l, syt *st) {
 	ast_push(a, parse_stmt(l, st)); return a;
 }
 
-typedef struct { tok_k tk; ast_k ak; s32 o; bool as; } op;
-
-static const op ops[] = {
-	{ TK_OP_MUL, AK_OP_MUL, 2, false },
-	{ TK_OP_DIV, AK_OP_DIV, 2, false },
-	{ TK_OP_MOD, AK_OP_MOD, 2, false },
-	{ TK_OP_ADD, AK_OP_ADD, 1, false },
-	{ TK_OP_SUB, AK_OP_SUB, 1, false },
-};
-
-static inline op ops_lookup(tok_k k) {
-	for (UINT i = 0; i < (sizeof (ops) / sizeof (*ops)); i += 1) {
-		if (k == ops[i].tk) { return ops[i]; }
-	} return (op){ 0 };
-}
-
 static inline void shunt(ast_a *aa, tok t, op o) {
 	ast *r = ast_a_pop(aa); ast *l = ast_a_pop(aa);
 
@@ -232,7 +221,7 @@ static ast *parse_expr(lex *l, syt *st) {
 			if (t.k == TK_NULL) { error(1, "todo: error: expected left parenthesis"); }
 			if (t.k == TK_LPAREN) { break; }
 
-			shunt(&as, t, ops_lookup(t.k));
+			shunt(&as, t, op_lookup(t.k, false));
 		}
 
 		/* TODO handle procedure calls */
@@ -240,10 +229,10 @@ static ast *parse_expr(lex *l, syt *st) {
 		lex_next(l);
 	} break;
 	default: /* Handle operators */ {
-		op o1; if ((o1 = ops_lookup(T.k)).tk == TK_NULL) { goto eox; }
+		op o1, o2; if ((o1 = op_lookup(T.k, false)).tk == TK_NULL) { goto eox; }
 
-		for (op o2 = ops_lookup(tok_a_peek(&ts).k);; o2 = ops_lookup(tok_a_peek(&ts).k)) {
-			if (o2.tk == TK_LPAREN || (o1.o > o2.o && (o1.o != o2.o || o1.as == true))) { break; }
+		for (o2 = op_lookup(tok_a_peek(&ts).k, false);; o2 = op_lookup(tok_a_peek(&ts).k, false)) {
+			if (o2.tk == TK_LPAREN || (o1.o < o2.o && (o1.o != o2.o || o1.as == true))) { break; }
 
 			shunt(&as, tok_a_pop(&ts), o2);
 		}
@@ -257,7 +246,7 @@ static ast *parse_expr(lex *l, syt *st) {
 		if (t.k == TK_LPAREN) { error(1, "LPAREN: TODO"); }
 		if (t.k == TK_RPAREN) { error(1, "RPAREN: TODO"); }
 
-		shunt(&as, t, ops_lookup(t.k));
+		shunt(&as, t, op_lookup(t.k, false));
 	}
 
 	return ast_a_pop(&as);
@@ -297,14 +286,37 @@ static ast *parse_int(lex *l, syt *st) {
 	ast *a = ast_init(); tok t = lex_kind(l, TK_INT);
 	a->k = AK_INT; a->ln = t.ln; a->cl = t.cl;
 
-	a->t = &TYPE(TY_S64); /* TODO properly determine type */
-	
 	if (!(a->s = strdup(t.s))) { error(1, "%s", SERR); }
 	if (!(a->v = val_parse_int(t.s)).k) { error(1, "%s: %s", t.s, SERR); }
 
+	/* Determine integer type */
+	// if (a->v.v_int <= U8_MAX) { a->t = &TYPE(TY_U8); }
+	// else if (a->v.v_int <= U16_MAX) { a->t = &TYPE(TY_U16); }
+	// else if (a->v.v_int <= U32_MAX) { a->t = &TYPE(TY_U32); }
+	// else if (a->v.v_int <= U64_MAX) { a->t = &TYPE(TY_U64); }
+	
+	a->t = &TYPE(TY_S64); // TODO remove temporary hack
+	
 	return a;
 }
 
+/* Lookup the operator associated with a particular token. */
+static op op_lookup(tok_k tk, bool unary) {
+	if (unary) switch (tk) {
+	case TK_OP_ADD: { return (op){ TK_OP_ADD, AK_OP_POS, 2, true }; }
+	case TK_OP_SUB: { return (op){ TK_OP_SUB, AK_OP_NEG, 2, true }; }
+	default: { return (op){ 0 }; } break;
+	}
+	else switch (tk) {
+	case TK_OP_ADD: { return (op){ TK_OP_ADD, AK_OP_ADD, 4, false }; } break;
+	case TK_OP_SUB: { return (op){ TK_OP_SUB, AK_OP_SUB, 4, false }; } break;
+	case TK_OP_MUL: { return (op){ TK_OP_MUL, AK_OP_MUL, 3, false }; } break;
+	case TK_OP_DIV: { return (op){ TK_OP_DIV, AK_OP_DIV, 3, false }; } break;
+	case TK_OP_MOD: { return (op){ TK_OP_MOD, AK_OP_MOD, 3, false }; } break;
+	default: { return (op){ 0 }; } break;
+	};
+}
+
 /* Recursively print an AST. */
 void ast_print(ast *a, UINT i) {
 	for (UINT j = 0; j != i; ++j) { printf("    "); }
diff --git a/src/parse.h b/src/parse.h
index f051e2c..9174273 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -19,6 +19,7 @@ typedef enum {
 
 	AK_STMT, AK_COMP, AK_DECL, AK_RETURN, AK_IF, AK_FOR,
 
+	AK_OP_POS, AK_OP_NEG,
 	AK_OP_ADD, AK_OP_SUB, AK_OP_MUL, AK_OP_DIV, AK_OP_MOD,
 
 	AK_VAR, AK_INT,