summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c60
-rw-r--r--test.toc3
-rw-r--r--tokenizer.c4
3 files changed, 64 insertions, 3 deletions
diff --git a/parse.c b/parse.c
index 55c2c6f..015666a 100644
--- a/parse.c
+++ b/parse.c
@@ -27,12 +27,24 @@ typedef struct {
};
} Type;
+typedef struct {
+ Identifier name;
+ Type type;
+} Param;
+
+typedef struct {
+ Array params;
+ Type ret_type;
+ Array stmts;
+} FnExpr; /* an expression such as fn(x: int) int {return 2 * x;} */
+
typedef enum {
EXPR_INT_LITERAL,
EXPR_FLOAT_LITERAL,
EXPR_IDENT, /* variable or constant */
EXPR_BINARY_OP,
- EXPR_UNARY_OP
+ EXPR_UNARY_OP,
+ EXPR_FN
} ExprKind;
typedef enum {
@@ -64,6 +76,7 @@ typedef struct Expression {
struct Expression *rhs;
} binary;
Identifier ident;
+ FnExpr fn;
};
} Expression;
@@ -169,6 +182,35 @@ static bool type_parse(Type *type, Parser *p) {
return false;
}
+static bool fn_expr_parse(FnExpr *f, Parser *p) {
+ Tokenizer *t = p->tokr;
+ /* only called when token is fn */
+ assert(token_is_kw(t->token, KW_FN));
+ t->token++;
+ if (!token_is_kw(t->token, KW_LPAREN)) {
+ tokr_err(t, "Expected '(' after 'fn'.");
+ return false;
+ }
+
+ t->token++;
+ if (!token_is_kw(t->token, KW_RPAREN)) {
+ tokr_err(t, "Expected ')' at end of parameter list.");
+ return false;
+ }
+ t->token++;
+ if (!token_is_kw(t->token, KW_LBRACE)) {
+ tokr_err(t, "Expected '{' to open function body.");
+ return false;
+ }
+ t->token++;
+ if (!token_is_kw(t->token, KW_RBRACE)) {
+ tokr_err(t, "Expected '}' to close function body.");
+ return false;
+ }
+ t->token++;
+ return true;
+}
+
#define NOT_AN_OP -1
static int op_precedence(Keyword op) {
switch (op) {
@@ -276,7 +318,18 @@ static bool expr_parse(Expression *e, Parser *p, Token *end) {
}
if (lowest_precedence == NOT_AN_OP) {
/* function calls, array accesses, etc. */
- tokr_err(t, "Not implemented yet.");
+ if (token_is_kw(t->token, KW_FN)) {
+ /* this is a function */
+ e->kind = EXPR_FN;
+ if (!fn_expr_parse(&e->fn, p))
+ return false;
+ if (t->token != end) {
+ tokr_err(t, "Direct function calling in an expression is not supported yet.");
+ /* TODO */
+ return false;
+ }
+ return true;
+ }
return false;
}
@@ -534,6 +587,9 @@ static void expr_fprint(FILE *out, Expression *e) {
expr_fprint(out, e->unary.of);
fprintf(out, ")");
break;
+ case EXPR_FN:
+ fprintf(out, "function!");
+ break;
}
}
diff --git a/test.toc b/test.toc
index 901d938..3cccd6d 100644
--- a/test.toc
+++ b/test.toc
@@ -1 +1,4 @@
x :- 3 + 4 - (3 + ((-3--b-5)+6++8)---+a+-4);
+main :- fn () {
+
+};
diff --git a/tokenizer.c b/tokenizer.c
index 5dbd9f4..d905bc8 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -193,8 +193,9 @@ static void tokenization_err(Tokenizer *t, const char *fmt, ...) {
}
/* to be used after tokenization */
-static void tokr_err(Tokenizer *t, const char *fmt, ...) {
+static void tokr_err_(const char *src_file, int src_line, Tokenizer *t, const char *fmt, ...) {
LineNo line = t->token->where.line;
+ err_fprint("At line %d of %s:\n", src_line, src_file); /* RELEASE: Remove this */
va_list args;
va_start(args, fmt);
err_vprint(line, t->token->where.code, fmt, args);
@@ -205,6 +206,7 @@ static void tokr_err(Tokenizer *t, const char *fmt, ...) {
t->token++;
}
}
+#define tokr_err(...) tokr_err_(__FILE__, __LINE__, __VA_ARGS__)
static void tokr_put_location(Tokenizer *tokr, Token *t) {
t->where.line = tokr->line;