commit 5c65136bf51aec19be5970dcd2e54c083c6b762a (tree)
parent aa0fab43e471bf910810eafb700506a5ad39ffa8
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Thu, 9 Jan 2025 07:27:24 +0100
more parser
Diffstat:
| M | parser.c | | | 267 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
1 file changed, 253 insertions(+), 14 deletions(-)
diff --git a/parser.c b/parser.c
@@ -1,3 +1,4 @@
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -9,6 +10,12 @@
const AstNodeIndex null_node = 0;
const AstTokenIndex null_token = ~(AstTokenIndex)(0);
+static AstNodeIndex parsePrefixExpr(Parser*);
+static AstNodeIndex parseTypeExpr(Parser*);
+static AstNodeIndex parseBlock(Parser* p);
+static AstNodeIndex parseLabeledStatement(Parser*);
+static AstNodeIndex parseExpr(Parser*);
+
typedef struct {
enum { FIELD_STATE_NONE, FIELD_STATE_SEEN, FIELD_STATE_END } tag;
union {
@@ -75,6 +82,12 @@ static AstTokenIndex eatToken(Parser* p, TokenizerTag tag) {
}
}
+static AstTokenIndex assertToken(Parser* p, TokenizerTag tag) {
+ const AstTokenIndex token = nextToken(p);
+ assert(p->token_tags[token] == tag);
+ return token;
+}
+
static void eatDocComments(Parser* p) {
while (eatToken(p, TOKEN_DOC_COMMENT) != null_token) { }
}
@@ -150,8 +163,6 @@ static AstNodeIndex parseCallconv(Parser* p) {
return 0; // tcc
}
-static AstNodeIndex parseTypeExpr(Parser*);
-
typedef struct {
AstNodeIndex align_expr, value_expr;
} NodeContainerField;
@@ -207,6 +218,29 @@ static AstNodeIndex expectContainerField(Parser* p) {
}
}
+static AstNodeIndex parseBuiltinCall(Parser* p) {
+ const AstNodeIndex builtin_token = assertToken(p, TOKEN_BUILTIN);
+ eatToken(p, TOKEN_L_PAREN);
+
+ CleanupScratch scratch_top __attribute__((__cleanup__(cleanupScratch)))
+ = initCleanupScratch(p);
+
+ while (true) {
+ if (eatToken(p, TOKEN_R_PAREN) != null_token)
+ break;
+
+ const AstNodeIndex param = parseExpr(p);
+ SLICE_APPEND(AstNodeIndex, &p->scratch, param);
+ // TODO finish
+ }
+
+ (void)builtin_token;
+
+ fprintf(stderr, "parseBuiltinCall not implemented\n");
+ exit(1);
+ return 0; // tcc
+}
+
static AstNodeIndex parsePrimaryTypeExpr(Parser* p) {
const TokenizerTag tok = p->token_tags[p->tok_i];
switch (tok) {
@@ -216,6 +250,7 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) {
case TOKEN_KEYWORD_ANYFRAME:
case TOKEN_STRING_LITERAL:
case TOKEN_BUILTIN:
+ return parseBuiltinCall(p);
case TOKEN_KEYWORD_FN:
case TOKEN_KEYWORD_IF:
case TOKEN_KEYWORD_SWITCH:
@@ -516,11 +551,56 @@ static AstNodeIndex parseAssignExpr(Parser* p) {
}
static AstNodeIndex parseVarDeclProto(Parser* p) {
- if (eatToken(p, TOKEN_KEYWORD_CONST) == null_token
- || eatToken(p, TOKEN_KEYWORD_VAR) == null_token)
+ AstTokenIndex mut_token;
+ if ((mut_token = eatToken(p, TOKEN_KEYWORD_CONST)) == null_token)
+ if ((mut_token = eatToken(p, TOKEN_KEYWORD_VAR)) == null_token)
+ return null_node;
+
+ expectToken(p, TOKEN_IDENTIFIER);
+ const AstNodeIndex type_node
+ = eatToken(p, TOKEN_COLON) == null_token ? 0 : parseTypeExpr(p);
+ const AstNodeIndex align_node = parseByteAlign(p);
+ const AstNodeIndex addrspace_node = parseAddrSpace(p);
+ const AstNodeIndex section_node = parseLinkSection(p);
+
+ if (section_node == 0 && addrspace_node == 0) {
+ if (align_node == 0) {
+ return addNode(
+ &p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_SIMPLE_VAR_DECL,
+ .main_token = mut_token,
+ .data = {
+ .lhs = type_node,
+ .rhs = 0,
+ },
+ });
+ }
+ fprintf(stderr, "parseVarDecl got something too complicated\n");
+ exit(1);
+ } else {
+ fprintf(stderr, "parseVarDecl got something too complicated\n");
+ exit(1);
+ }
+ return 0; // tcc
+}
+
+static AstTokenIndex parseBreakLabel(Parser* p) {
+ if (eatToken(p, TOKEN_COLON) == null_node)
+ return null_node;
+ return expectToken(p, TOKEN_IDENTIFIER);
+}
+
+static AstNodeIndex parseCurlySuffixExpr(Parser* p) {
+ const AstNodeIndex lhs = parseTypeExpr(p);
+ if (lhs == 0)
return null_node;
- fprintf(stderr, "parseVarDeclProto: parsing vars is not supported\n");
+ const AstTokenIndex lbrace = eatToken(p, TOKEN_L_BRACE);
+ if (lbrace == null_token)
+ return lhs;
+
+ fprintf(stderr, "parseCurlySuffixExpr is not implemented\n");
exit(1);
return 0; // tcc
}
@@ -619,25 +699,184 @@ static OperInfo operTable(TokenizerTag tok_tag) {
}
}
+static AstNodeIndex parseExprPrecedence(Parser* p, int32_t min_prec) {
+ (void)p;
+ assert(min_prec >= 0);
+
+ AstNodeIndex node = parsePrefixExpr(p);
+ if (node == 0)
+ return null_node;
+
+ int8_t banned_prec = -1;
+
+ while (true) {
+ const TokenizerTag tok_tag = p->token_tags[p->tok_i];
+ const OperInfo info = operTable(tok_tag);
+ if (info.prec < min_prec)
+ break;
+
+ assert(info.prec != banned_prec);
+
+ const AstTokenIndex oper_token = nextToken(p);
+ if (tok_tag == TOKEN_KEYWORD_CATCH) {
+ fprintf(stderr, "parsePayload not supported\n");
+ exit(1);
+ return 0; // tcc
+ }
+ const AstNodeIndex rhs = parseExprPrecedence(p, info.prec + 1);
+ assert(rhs != 0);
+
+ node = addNode(
+ &p->nodes,
+ (AstNodeItem) {
+ .tag = info.tag,
+ .main_token = oper_token,
+ .data = {
+ .lhs = node,
+ .rhs = rhs,
+ },
+ });
+
+ if (info.assoc == ASSOC_NONE)
+ banned_prec = info.prec;
+ }
+
+ return node;
+}
+
+static AstNodeIndex parseExpr(Parser* p) { return parseExprPrecedence(p, 0); }
+
+static AstNodeIndex parsePrimaryExpr(Parser* p) {
+ const char* tok = tokenizerGetTagString(p->token_tags[p->tok_i]);
+ switch (p->token_tags[p->tok_i]) {
+ case TOKEN_KEYWORD_ASM:
+ case TOKEN_KEYWORD_IF:
+ fprintf(stderr, "parsePrimaryExpr does not implement %s\n", tok);
+ exit(1);
+ break;
+ case TOKEN_KEYWORD_BREAK:
+ return addNode(
+ &p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_BREAK,
+ .main_token = nextToken(p),
+ .data = {
+ .lhs = parseBreakLabel(p),
+ .rhs = parseExpr(p),
+ },
+ });
+ case TOKEN_KEYWORD_CONTINUE:
+ return addNode(
+ &p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_CONTINUE,
+ .main_token = nextToken(p),
+ .data = {
+ .lhs = parseBreakLabel(p),
+ .rhs = parseExpr(p),
+ },
+ });
+ case TOKEN_KEYWORD_COMPTIME:
+ case TOKEN_KEYWORD_NOSUSPEND:
+ case TOKEN_KEYWORD_RESUME:
+ case TOKEN_KEYWORD_RETURN:
+ fprintf(stderr, "parsePrimaryExpr does not implement %s\n", tok);
+ exit(1);
+ return 0; // tcc
+ case TOKEN_IDENTIFIER:
+ if (p->token_tags[p->tok_i + 1] == TOKEN_COLON) {
+ switch (p->token_tags[p->tok_i + 2]) {
+ case TOKEN_KEYWORD_INLINE:
+ case TOKEN_KEYWORD_FOR:
+ case TOKEN_KEYWORD_WHILE:
+ fprintf(stderr, "parsePrimaryExpr NotImplemented\n");
+ exit(1);
+ return 0; // tcc
+ case TOKEN_L_BRACE:
+ p->tok_i += 2;
+ return parseBlock(p);
+ default:
+ return parseCurlySuffixExpr(p);
+ }
+ } else {
+ return parseCurlySuffixExpr(p);
+ }
+ case TOKEN_KEYWORD_INLINE:
+ case TOKEN_KEYWORD_FOR:
+ case TOKEN_KEYWORD_WHILE:
+ fprintf(stderr, "parsePrimaryExpr does not implement %s\n", tok);
+ exit(1);
+ return 0; // tcc
+ case TOKEN_L_BRACE:
+ return parseBlock(p);
+ default:
+ return parseCurlySuffixExpr(p);
+ }
+}
+
+static AstNodeIndex parsePrefixExpr(Parser* p) {
+ AstNodeTag tag;
+ switch (p->token_tags[p->tok_i]) {
+ case TOKEN_BANG:
+ tag = AST_NODE_BOOL_NOT;
+ break;
+ case TOKEN_MINUS:
+ tag = AST_NODE_NEGATION;
+ break;
+ case TOKEN_TILDE:
+ tag = AST_NODE_BIT_NOT;
+ break;
+ case TOKEN_MINUS_PERCENT:
+ tag = AST_NODE_NEGATION_WRAP;
+ break;
+ case TOKEN_AMPERSAND:
+ tag = AST_NODE_ADDRESS_OF;
+ break;
+ case TOKEN_KEYWORD_TRY:
+ tag = AST_NODE_TRY;
+ break;
+ case TOKEN_KEYWORD_AWAIT:
+ tag = AST_NODE_AWAIT;
+ break;
+ default:
+ return parsePrimaryExpr(p);
+ }
+ return addNode(
+ &p->nodes,
+ (AstNodeItem) {
+ .tag = tag,
+ .main_token = nextToken(p),
+ .data = {
+ .lhs = parsePrefixExpr(p),
+ .rhs = 0,
+ },
+ });
+}
+
static AstNodeIndex expectVarDeclExprStatement(Parser* p) {
CleanupScratch scratch_top __attribute__((__cleanup__(cleanupScratch)))
= initCleanupScratch(p);
- // while(true) {
- // const AstNodeIndex var_decl_proto = parseVarDeclProto(p);
- // if (var_decl_proto != 0) {
- // SLICE_APPEND(AstNodeIndex, &p->scratch, var_decl_proto);
- // } else {
+ while (true) {
+ const AstNodeIndex var_decl_proto = parseVarDeclProto(p);
+ if (var_decl_proto != 0) {
+ SLICE_APPEND(AstNodeIndex, &p->scratch, var_decl_proto);
+ } else {
+ const AstNodeIndex expr = parseExpr(p);
+ SLICE_APPEND(AstNodeIndex, &p->scratch, expr);
+ }
+ if (eatToken(p, TOKEN_COMMA) == null_node)
+ break;
+ }
- // }
- //}
+ const uint32_t lhs_count = p->scratch.len - scratch_top.old_len;
+ assert(lhs_count > 0);
- fprintf(stderr, "expectVarDeclExprStatement not implemented\n");
+ fprintf(stderr, "expectVarDeclExprStatement only partially implemented\n");
exit(1);
return 0; // tcc
}
-static AstNodeIndex parseLabeledStatement(Parser*);
static AstNodeIndex expectStatement(Parser* p, bool allow_defer_var) {
if (eatToken(p, TOKEN_KEYWORD_COMPTIME) != null_token) {
fprintf(stderr, "expectStatement: comptime keyword not supported\n");