aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-09-23 15:52:09 +0200
committerHimbeer <himbeer@disroot.org>2024-09-23 15:52:09 +0200
commitc9a22c04a32f3db2b0c2a70febfafcefa26f6f2a (patch)
treeb71b44f1aeb3e72a12a5ecfffb7c5e3d67468200
parentf7969e4a66b8a2b81405923a2a4fe19ba6095cb7 (diff)
Implement expressions
-rw-r--r--Makefile1
-rw-r--r--include/expr.h197
-rw-r--r--include/parse.h14
-rw-r--r--src/parse.c18
4 files changed, 213 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index ff5c0c4..a95053b 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,7 @@
BINOUT = .bin
HDR = \
+ include/expr.h \
include/lex.h \
include/parse.h \
include/type.h \
diff --git a/include/expr.h b/include/expr.h
new file mode 100644
index 0000000..93b9204
--- /dev/null
+++ b/include/expr.h
@@ -0,0 +1,197 @@
+#ifndef CERC_EXPR_H
+#define CERC_EXPR_H
+#include <stdbool.h>
+#include "lex.h"
+#include "type.h"
+
+struct grouping_e {
+ struct disjunction_e *inner;
+};
+
+struct number_e {
+ struct number value;
+ struct type type;
+};
+
+struct array_e {
+ struct cer_array meta;
+ struct disjunction_e *elems;
+ int elemsz, elemlen;
+};
+
+enum literal {
+ LIT_BOOL,
+ LIT_STRING,
+ LIT_NUMBER,
+ LIT_ARRAY,
+};
+
+struct literal_e {
+ enum literal kind;
+ union {
+ bool b;
+ const char *str;
+ struct number_e num;
+ struct array_e arr;
+ } lit;
+};
+
+struct path {
+ const char **segments;
+ int segsz, seglen;
+};
+
+struct call_e {
+ struct path path;
+ struct disjunction_e *args;
+ int argsz, arglen;
+};
+
+enum primary {
+ PRM_GROUPING,
+ PRM_LITERAL,
+ PRM_CALL,
+ PRM_PATH,
+};
+
+struct primary_e {
+ enum primary kind;
+ union {
+ struct grouping_e grp;
+ struct literal_e lit;
+ struct call_e call;
+ struct path path;
+ } prim;
+};
+
+enum unary_postfix {
+ UPS_DEREF,
+ UPS_TRY,
+ UPS_ASSERT,
+};
+
+struct unarypost_e {
+ enum unary_postfix op;
+ struct primary_e prim;
+};
+
+enum unary_prefix {
+ UPR_NUMNEG,
+ UPR_BOOLNEG,
+ UPR_BITNEG,
+};
+
+struct unarypre_e {
+ enum unary_prefix op;
+ struct unarypost_e post;
+};
+
+struct bitfactor_e {
+ struct unarypre_e lhs, *rhs;
+ int rhssz, rhslen;
+};
+
+struct bitsummand_e {
+ struct bitfactor_e lhs, *rhs;
+ int rhssz, rhslen;
+};
+
+struct bin_e {
+ struct bitsummand_e lhs, *rhs;
+ int rhssz, rhslen;
+};
+
+enum factor {
+ FCT_MUL,
+ FCT_DIV,
+ FCT_REM,
+};
+
+struct factor_rhs {
+ enum factor factor;
+ struct bin_e bin;
+};
+
+struct factor_e {
+ struct bin_e lhs;
+ struct factor_rhs *rhs;
+ int rhssz, rhslen;
+};
+
+enum numeral {
+ NUM_ADD,
+ NUM_SUB,
+};
+
+struct num_rhs {
+ enum numeral num;
+ struct factor_e factor;
+};
+
+struct num_e {
+ struct factor_e lhs;
+ struct num_rhs *rhs;
+ int rhssz, rhslen;
+};
+
+enum term {
+ TRM_NUM,
+ TRM_SHL,
+ TRM_SHR,
+};
+
+struct term_e {
+ enum term term;
+ struct num_e lhs, rhs;
+};
+
+enum comparison {
+ CMP_LT,
+ CMP_LE,
+ CMP_GT,
+ CMP_GE,
+};
+
+struct cmp_rhs {
+ enum comparison cmp;
+ struct term_e term;
+};
+
+struct cmp_e {
+ struct term_e lhs;
+ struct cmp_rhs *rhs;
+ int rhssz, rhslen;
+};
+
+struct eq_e {
+ bool invert;
+ struct cmp_e lhs, rhs;
+};
+
+enum boolean {
+ B_EQ,
+ B_CMP,
+};
+
+struct bool_e {
+ enum boolean kind;
+ union {
+ struct eq_e eq;
+ struct cmp_e cmp;
+ } cond;
+};
+
+struct conjunction_e {
+ // At least one required
+ struct bool_e *bools;
+ int boolsz, boollen;
+};
+
+// Entry point
+struct disjunction_e {
+ // At least one required
+ struct conjunction_e *cons;
+ int consz, conlen;
+};
+
+#endif
diff --git a/include/parse.h b/include/parse.h
index 8cc4985..de30f39 100644
--- a/include/parse.h
+++ b/include/parse.h
@@ -1,7 +1,10 @@
#ifndef CERC_PARSE_H
#define CERC_PARSE_H
-#include "lex.h"
-#include "type.h"
+#include "expr.h"
+
+struct ast_expr {
+ struct disjunction_e dis;
+};
struct ast_externfunc {
const char *name;
@@ -47,13 +50,8 @@ struct ast_const_global {
} value;
};
-struct ast_path {
- const char **segments;
- int len, cap;
-};
-
struct ast_import {
- struct ast_path path;
+ struct path path;
const char *name;
};
diff --git a/src/parse.c b/src/parse.c
index 2fa3ee4..ef4f4dc 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -19,19 +19,19 @@ error(struct location loc, const char *fmt, ...)
}
static void
-append(struct ast_path *path, const char *name)
+append(struct path *path, const char *name)
{
- if (path->len >= path->cap) {
- path->cap *= 2;
- size_t sz = sizeof(const char *) * path->cap;
+ if (path->seglen >= path->segsz) {
+ path->segsz *= 2;
+ size_t sz = sizeof(const char *) * path->segsz;
path->segments = must_realloc(path->segments, sz);
}
- path->segments[path->len++] = name;
+ path->segments[path->seglen++] = name;
}
static bool
-parse_path(struct lexer *lexer, struct ast_path *out)
+parse_path(struct lexer *lexer, struct path *out)
{
struct token name;
@@ -41,8 +41,8 @@ parse_path(struct lexer *lexer, struct ast_path *out)
out->segments = must_calloc(1, sizeof(const char *));
out->segments[0] = name.info.str;
- out->len = 1;
- out->cap = 1;
+ out->seglen = 1;
+ out->segsz = 1;
while (match(lexer, T_MODDELIM)) {
if (lex(lexer, &name) != T_NAME) {
@@ -70,7 +70,7 @@ parse_import(struct lexer *lexer, struct ast_import *out)
out->name = token.info.str;
} else {
unlex(lexer, &token);
- out->name = out->path.segments[out->path.len - 1];
+ out->name = out->path.segments[out->path.seglen - 1];
}
if (!match(lexer, T_SEMICOLON)) {