aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c110
1 files changed, 88 insertions, 22 deletions
diff --git a/src/parser.c b/src/parser.c
index d10a82f..44888ae 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -18,22 +18,65 @@
#endif
#define SIZE_WDTH (sizeof(size_t) * CHAR_BIT)
-typedef idx_t_ parsefn(struct ast *, struct lexemes) __attribute__((nonnull));
-static parsefn parseblk, parsedecl, parseexpr, parseproto, parsestmt, parsetype;
+typedef idx_t_ parsefn(struct ast *, struct lexemes)
+ __attribute__((nonnull));
+static parsefn parseblk, parseexpr, parsefunc, parseproto, parsestmt, parsetype;
+static idx_t_ parsedecl(struct ast *, struct lexemes, bool)
+ __attribute__((nonnull));
static struct ast mkast(void);
-static idx_t_ astalloc(struct ast *) __attribute__((nonnull));
-static void astresz(struct ast *) __attribute__((nonnull));
+static idx_t_ astalloc(struct ast *)
+ __attribute__((nonnull));
+static void astresz(struct ast *)
+ __attribute__((nonnull));
static size_t toksidx;
+idx_t_
+fwdnode(struct ast ast, idx_t_ i)
+{
+ while (likely(i < ast.len)) {
+ switch (ast.kinds[i]) {
+ case ASTBLK:
+ i = ast.kids[i].lhs == AST_EMPTY ? i + 1 : ast.kids[i].rhs;
+ break;
+ case ASTDECL:
+ case ASTPDECL:
+ i = ast.kids[i].rhs == AST_EMPTY ? ast.kids[i].lhs
+ : ast.kids[i].rhs;
+ break;
+ case ASTRET:
+ if (ast.kids[i].rhs == AST_EMPTY)
+ return i + 1;
+ i = ast.kids[i].rhs;
+ break;
+ case ASTBINADD:
+ case ASTBINSUB:
+ case ASTCDECL:
+ case ASTPCDECL:
+ case ASTFN:
+ i = ast.kids[i].rhs;
+ break;
+ case ASTIDENT:
+ case ASTNUMLIT:
+ case ASTTYPE:
+ return i + 1;
+ case ASTFNPROTO:
+ assert("analyzer: Not reachable");
+ __builtin_unreachable();
+ }
+ }
+
+ return i;
+}
+
struct ast
parsetoks(struct lexemes toks)
{
struct ast ast = mkast();
for (;;) {
- (void)parsedecl(&ast, toks);
+ (void)parsedecl(&ast, toks, true);
if (toks.kinds[toksidx] == LEXEOF)
break;
}
@@ -68,11 +111,20 @@ parseblk(struct ast *ast, struct lexemes toks)
}
idx_t_
-parsedecl(struct ast *ast, struct lexemes toks)
+parsedecl(struct ast *ast, struct lexemes toks, bool toplvl)
{
idx_t_ i = astalloc(ast);
ast->lexemes[i] = toksidx;
+ bool pub;
+ if (toplvl && toks.kinds[toksidx] == LEXIDENT && toks.strs[toksidx].len == 3
+ && memcmp("pub", toks.strs[toksidx].p, 3) == 0)
+ {
+ pub = true;
+ toksidx++;
+ } else
+ pub = false;
+
if (toks.kinds[toksidx++] != LEXIDENT)
err("parser: Expected identifier");
if (toks.kinds[toksidx++] != LEXCOLON)
@@ -86,28 +138,49 @@ parsedecl(struct ast *ast, struct lexemes toks)
case LEXSEMI:
if (ast->kids[i].lhs == AST_EMPTY)
err("parser: No type provided in non-assigning declaration");
- ast->kinds[i] = ASTDECL;
+ ast->kinds[i] = ASTDECL + pub;
ast->kids[i].rhs = AST_EMPTY;
return i;
case LEXCOLON:
- ast->kinds[i] = ASTCDECL;
+ ast->kinds[i] = ASTCDECL + pub;
break;
case LEXEQ:
- ast->kinds[i] = ASTDECL;
+ ast->kinds[i] = ASTDECL + pub;
break;
default:
- err("parser: Expected semicolon or equals");
+ err("parser: Expected colon, equals, or semicolon");
}
- idx_t_ rhs = parseexpr(ast, toks);
+ bool func = toks.kinds[toksidx] == LEXLPAR;
+ if (func && ast->kinds[i] - pub == ASTDECL)
+ err("Cannot assign function to mutable variable");
+
+ idx_t_ rhs = (func ? parsefunc : parseexpr)(ast, toks);
ast->kids[i].rhs = rhs;
- if (toks.kinds[toksidx++] != LEXSEMI)
+ if (!func && toks.kinds[toksidx++] != LEXSEMI)
err("parser: Expected semicolon");
return i;
}
idx_t_
+parsefunc(struct ast *ast, struct lexemes toks)
+{
+ idx_t_ i = astalloc(ast);
+ ast->lexemes[i] = toksidx;
+
+ assert(toks.kinds[toksidx] == LEXLPAR);
+
+ ast->kinds[i] = ASTFN;
+ idx_t_ lhs = parseproto(ast, toks);
+ idx_t_ rhs = parseblk(ast, toks);
+ ast->kids[i].lhs = lhs;
+ ast->kids[i].rhs = rhs;
+
+ return i;
+}
+
+idx_t_
parseexpr(struct ast *ast, struct lexemes toks)
{
idx_t_ i = astalloc(ast);
@@ -122,13 +195,6 @@ parseexpr(struct ast *ast, struct lexemes toks)
toksidx++;
ast->kinds[i] = ASTIDENT;
break;
- case LEXLPAR:
- ast->kinds[i] = ASTFN;
- idx_t_ lhs = parseproto(ast, toks);
- idx_t_ rhs = parseblk(ast, toks);
- ast->kids[i].lhs = lhs;
- ast->kids[i].rhs = rhs;
- break;
default:
err("parser: Expected expression");
}
@@ -164,7 +230,7 @@ parsestmt(struct ast *ast, struct lexemes toks)
err("parser: Expected identifier");
struct strview sv = toks.strs[toksidx];
- if (strncmp("return", sv.p, sv.len) == 0) {
+ if (sv.len == 6 && memcmp(sv.p, "return", 6) == 0) {
i = astalloc(ast);
ast->lexemes[i] = toksidx++;
ast->kinds[i] = ASTRET;
@@ -175,9 +241,9 @@ parsestmt(struct ast *ast, struct lexemes toks)
if (toks.kinds[toksidx++] != LEXSEMI)
err("parser: Expected semicolon");
} else if (toks.kinds[toksidx + 1] == LEXCOLON)
- i = parsedecl(ast, toks);
+ i = parsedecl(ast, toks, false);
else
- i = parseexpr(ast, toks);
+ err("parser: Invalid statement");
return i;
}