feat: implement conditions

This commit is contained in:
samsonium
2026-10-14 19:56:27 +03:00
parent 4a908f9fd8
commit 83ff0b5774
11 changed files with 731 additions and 25 deletions
+213 -4
View File
@@ -120,6 +120,8 @@ static fzl_nodetype_t unary_op_to_type(fzl_toktype_t type)
return FZL_NODETYPE_UNARY_PLUS;
case FZL_TOKTYPE_MINUS:
return FZL_NODETYPE_UNARY_MINUS;
case FZL_TOKTYPE_NOT:
return FZL_NODETYPE_NOT;
default:
return 0;
@@ -144,6 +146,11 @@ fzl_node_t *parse_primary(fzl_parser_t *parser)
fzl_token_t *tok = consume(parser);
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
}
else if (is(parser, FZL_TOKTYPE_BOOL_LITERAL))
{
fzl_token_t *tok = consume(parser);
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
}
else if (is(parser, FZL_TOKTYPE_LPAREN))
{
consume(parser);
@@ -241,7 +248,8 @@ fzl_node_t *parse_unary(fzl_parser_t *parser)
if (!parser)
return NULL;
if (!is(parser, FZL_TOKTYPE_MINUS) && !is(parser, FZL_TOKTYPE_PLUS))
if (!is(parser, FZL_TOKTYPE_MINUS) && !is(parser, FZL_TOKTYPE_PLUS) &&
!is(parser, FZL_TOKTYPE_NOT))
return parse_postfix(parser);
fzl_token_t *op = consume(parser);
@@ -372,12 +380,131 @@ fzl_node_t *parse_term(fzl_parser_t *parser)
return left;
}
// Expression parsing
fzl_node_t *parse_expression(fzl_parser_t *parser)
// Parse conditional operations
fzl_node_t *parse_cond(fzl_parser_t *parser)
{
return parse_term(parser);
if (!parser)
return NULL;
fzl_node_t *left = parse_term(parser);
fzl_node_t *right = NULL;
if (!left)
return NULL;
while (is(parser, FZL_TOKTYPE_EQEQ) || is(parser, FZL_TOKTYPE_NEQ) ||
is(parser, FZL_TOKTYPE_LANGLE) || is(parser, FZL_TOKTYPE_LEQ) ||
is(parser, FZL_TOKTYPE_RANGLE) || is(parser, FZL_TOKTYPE_REQ))
{
fzl_token_t *op = consume(parser);
right = parse_term(parser);
if (!right)
{
snprintf(plast_err, sizeof(plast_err), "unfinished expression at %ld:%ld",
op->ln, op->cn);
return NULL;
}
fzl_node_t *result;
switch (op->type)
{
case FZL_TOKTYPE_EQEQ:
result = fzl_mknode(FZL_NODETYPE_EQUAL, op);
break;
case FZL_TOKTYPE_NEQ:
result = fzl_mknode(FZL_NODETYPE_NEQUAL, op);
break;
case FZL_TOKTYPE_LANGLE:
result = fzl_mknode(FZL_NODETYPE_LESS, op);
break;
case FZL_TOKTYPE_LEQ:
result = fzl_mknode(FZL_NODETYPE_LESS_EQUAL, op);
break;
case FZL_TOKTYPE_RANGLE:
result = fzl_mknode(FZL_NODETYPE_GREATER, op);
break;
case FZL_TOKTYPE_REQ:
result = fzl_mknode(FZL_NODETYPE_GREATER_EQUAL, op);
break;
default:
return NULL;
}
result->binary_op.left = left;
result->binary_op.right = right;
left = result;
}
return left;
}
// Parse conditional &&
fzl_node_t *parse_and(fzl_parser_t *parser)
{
if (!parser)
return NULL;
fzl_node_t *left = parse_cond(parser);
fzl_node_t *right = NULL;
if (!left)
return NULL;
while (is(parser, FZL_TOKTYPE_DAMPERSAND))
{
fzl_token_t * or = consume(parser);
right = parse_cond(parser);
if (!right)
{
snprintf(plast_err, sizeof(plast_err), "unfinished expression at %ld:%ld",
or->ln, or->cn);
return NULL;
}
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_AND, or);
node->binary_op.left = left;
node->binary_op.right = right;
left = node;
}
return left;
}
// Parse conditional ||
fzl_node_t *parse_or(fzl_parser_t *parser)
{
if (!parser)
return NULL;
fzl_node_t *left = parse_and(parser);
fzl_node_t *right = NULL;
if (!left)
return NULL;
while (is(parser, FZL_TOKTYPE_DVBAR))
{
fzl_token_t * or = consume(parser);
right = parse_and(parser);
if (!right)
{
snprintf(plast_err, sizeof(plast_err), "unfinished expression at %ld:%ld",
or->ln, or->cn);
return NULL;
}
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_OR, or);
node->binary_op.left = left;
node->binary_op.right = right;
left = node;
}
return left;
}
// Expression parsing
fzl_node_t *parse_expression(fzl_parser_t *parser) { return parse_and(parser); }
// Statement parsing
fzl_node_t *parse_statement(fzl_parser_t *parser)
{
@@ -447,6 +574,88 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
return left;
}
if (is(parser, FZL_TOKTYPE_IF))
{
fzl_token_t *if_tok = consume(parser);
fzl_token_t *lparen = consume(parser);
if (lparen->type != FZL_TOKTYPE_LPAREN)
{
snprintf(plast_err, sizeof(plast_err),
"expected '(' before condition at %ld:%ld", lparen->ln,
lparen->cn);
return NULL;
}
fzl_node_t *condition = parse_expression(parser);
if (!condition)
return NULL;
fzl_token_t *rparen = consume(parser);
if (rparen->type != FZL_TOKTYPE_RPAREN)
{
snprintf(plast_err, sizeof(plast_err),
"expected ')' after condition at %ld:%ld", rparen->ln,
rparen->cn);
return NULL;
}
fzl_node_t *else_block = NULL;
fzl_node_t *true_block = parse_statement(parser);
if (!true_block)
return NULL;
if (is(parser, FZL_TOKTYPE_ELSE))
{
consume(parser); // else
else_block = parse_statement(parser);
if (!else_block)
return NULL;
}
fzl_node_t *stmt_node = fzl_mknode(FZL_NODETYPE_CONDITIONAL, if_tok);
stmt_node->cond.condition = condition;
stmt_node->cond.true_block = true_block;
stmt_node->cond.else_block = else_block;
return stmt_node;
}
if (is(parser, FZL_TOKTYPE_LBRACE))
{
fzl_token_t *block_tok = consume(parser);
size_t remainder = 2;
size_t count = 0;
fzl_node_t **stmts = malloc(remainder * sizeof(fzl_node_t *));
while (peek(parser) && !is(parser, FZL_TOKTYPE_RBRACE))
{
fzl_node_t *node = parse_statement(parser);
if (!node)
return NULL;
if (remainder <= count)
{
remainder *= 2;
stmts = realloc(stmts, remainder);
}
stmts[count++] = node;
}
fzl_token_t *rbrace = consume(parser);
if (!rbrace || rbrace->type != FZL_TOKTYPE_RBRACE)
{
snprintf(plast_err, sizeof(plast_err),
"missing '}' after block at %ld:%ld", rbrace->ln, rbrace->cn);
return NULL;
}
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_BLOCK, block_tok);
node->list.entries = stmts;
node->list.entry_count = count;
return node;
}
return parse_expression(parser);
}