aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c115
1 files changed, 111 insertions, 4 deletions
diff --git a/src/parser.c b/src/parser.c
index 6ea8d1d..52c5bfe 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -70,7 +70,7 @@ static CHECK_RESULT int parser_parse_body_loop(Parser *self, Buffer *body_list,
}
/*
-LHS = 'const'|'var' IDENTIFIER
+LHS = 'const'|'var' TOK_IDENTIFIER
*/
static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignment) {
bool isConst;
@@ -92,6 +92,12 @@ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result, bool *a
return_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result));
lhsexpr_init(*result, isConst, var_name);
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COLON, &match));
+ if(match) {
+ return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER));
+ (*result)->type_name = self->tokenizer.value.identifier;
+ }
+
return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match));
if(match) {
*assignment = bool_true;
@@ -165,7 +171,7 @@ static CHECK_RESULT int parser_parse_function_args(Parser *self, FunctionCall *f
}
/*
-VARIABLE = IDENTIFIER
+VARIABLE = TOK_IDENTIFIER
FUNC_CALL_OR_VARIABLE = VARIABLE '(' FUNC_ARGS ')'
*/
static CHECK_RESULT int parser_parse_function_call_or_variable(Parser *self, Ast *expr) {
@@ -227,10 +233,11 @@ static CHECK_RESULT int parser_parse_number(Parser *self, Ast *rhs_expr) {
}
/*
-RHS = STRING | NUMBER | FUNC_CALL_OR_VARIABLE
+RHS_S = STRING | NUMBER | FUNC_CALL_OR_VARIABLE
*/
-static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
+static CHECK_RESULT int parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) {
bool match;
+ *rhs_expr = ast_none();
return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &match));
if(match) {
@@ -254,6 +261,95 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
return PARSER_UNEXPECTED_TOKEN;
}
+static CHECK_RESULT int parser_parse_rhs_binop(Parser *self, Ast *expr);
+
+/*
+RHS_BINOP_PAREN = '(' RHS_BINOP ')' (TOK_BINOP RHS_BINOP)
+*/
+static CHECK_RESULT int parser_parse_rhs_binop_paren(Parser *self, bool *match, Ast *expr) {
+ bool binop_match;
+ Ast lhs;
+ Ast rhs;
+ BinopType binop_type;
+
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, match));
+ if(!*match)
+ return PARSER_OK;
+
+ return_if_error(parser_parse_rhs_binop(self, &lhs));
+ return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN));
+
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &binop_match));
+ if(!binop_match) {
+ *expr = lhs;
+ return PARSER_OK;
+ }
+ binop_type = self->tokenizer.value.binop_type;
+
+ return_if_error(parser_parse_rhs_binop(self, &rhs));
+ return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop));
+ binop_init(expr->value.binop);
+ expr->value.binop->type = binop_type;
+ expr->value.binop->lhs = lhs;
+ expr->value.binop->rhs = rhs;
+ expr->type = AST_BINOP;
+ return PARSER_OK;
+}
+
+/*
+RHS_BINOP_WO_PAREN = RHS_S | (RHS_S TOK_BINOP RHS_BINOP)
+*/
+static CHECK_RESULT int parser_parse_rhs_binop_without_paren(Parser *self, Ast *expr) {
+ bool match;
+ Ast lhs;
+ Ast rhs;
+ BinopType binop_type;
+
+ return_if_error(parser_parse_rhs_single_expr(self, &lhs));
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match));
+ if(!match) {
+ *expr = lhs;
+ return PARSER_OK;
+ }
+ binop_type = self->tokenizer.value.binop_type;
+
+ return_if_error(parser_parse_rhs_binop(self, &rhs));
+ return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop));
+ binop_init(expr->value.binop);
+ expr->value.binop->type = binop_type;
+ expr->value.binop->lhs = lhs;
+ expr->value.binop->rhs = rhs;
+ expr->type = AST_BINOP;
+ return PARSER_OK;
+}
+
+/*
+RHS_BINOP = RHS_BINOP_PAREN | RHS_BINOP_WO_PAREN
+
+Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis.
+*/
+int parser_parse_rhs_binop(Parser *self, Ast *expr) {
+ bool match;
+ return_if_error(parser_parse_rhs_binop_paren(self, &match, expr));
+ if(match)
+ return PARSER_OK;
+ return parser_parse_rhs_binop_without_paren(self, expr);
+}
+
+/*
+RHS = RHS_BINOP ';'
+
+Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis.
+*/
+static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
+ /* TODO: If binop only contains one expression, then use that directly for @rhs_expr */
+ return_if_error(parser_parse_rhs_binop(self, rhs_expr));
+
+ /* TODO: Implement this */
+ /*binop_reorder_by_precedence(binop);*/
+ return PARSER_OK;
+}
+
/*
RHS_START = CLOSURE | IMPORT | RHS
*/
@@ -312,6 +408,17 @@ int parser_parse_body(Parser *self, Ast *ast) {
*ast = rhs_expr;
}
+ if(rhs_expr.type == AST_BINOP) {
+ bool match;
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match));
+ if(!match) {
+ /* TODO: Specify all the binop characters instead of "binop" which doesn't make sense for the user */
+ self->error = tokenizer_create_error(&self->tokenizer, "Expected ';' or binop");
+ return PARSER_UNEXPECTED_TOKEN;
+ }
+ return PARSER_OK;
+ }
+
/* TODO: Check for struct and tables */
if(rhs_expr.type != AST_FUNCTION_DECL)
return_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON));