refactor: nud and led have differetn responasblires

So now nud and led do what they were supposed to do i guess, now i
thinks is just adjusting infix and postfix and all bd funcions to act on
operator instead.
This commit is contained in:
2026-05-13 17:35:52 -06:00
parent 70ab06964c
commit 6294121e91
2 changed files with 209 additions and 288 deletions

View File

@@ -38,6 +38,7 @@ typedef enum {
PARSER_UNMATCHED_PAREN, PARSER_UNMATCHED_PAREN,
PARSER_OUT_OF_MEMORY, PARSER_OUT_OF_MEMORY,
PARSER_INVALID_TOKENIZE, PARSER_INVALID_TOKENIZE,
PARSER_UNEXMECTED_EOF,
} ParserErr; } ParserErr;
typedef struct { typedef struct {
@@ -76,8 +77,8 @@ typedef struct {
} ParserU8Result; } ParserU8Result;
Node token_to_node(Token token); Node token_to_node(Token token);
NodeResult nud(Token token); // Null denotation TreeResult nud(ArraySlice *slice, Arena *arena, Token token); // Null denotation
NodeResult led(Token token); // Left denotation TreeResult led(ArraySlice *slice, Arena *arena, Node *left, Token token); // Left denotation
ParserU8Result prefix_rbp(Node node); ParserU8Result prefix_rbp(Node node);
ParserU8Result postfix_lbp(Node node); ParserU8Result postfix_lbp(Node node);

View File

@@ -119,166 +119,175 @@ ParserU8Result infix_rbp(Node node) {
}; };
} }
} }
NodeResult led(Token token) {
if (token.type == TOKEN_INTEGER) { TreeResult led(
return (NodeResult) { ArraySlice *slice,
.is_valid = false, Arena *arena,
.err = PARSER_UNEXPECTED_TOKEN, Node *left,
}; Token token
} ) {
arena_ensure_capacity(
arena,
sizeof(Node),
alignof(Node)
);
Node *node = arena_unwrap_pointer(
arena_alloc(
arena,
sizeof(Node),
alignof(Node)
)
);
switch (token.op) { switch (token.op) {
// Binary operators
case OP_ADD: case OP_ADD:
return (NodeResult) {
.is_valid = true,
.node = (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
}
};
case OP_SUB: case OP_SUB:
return (NodeResult) {
.is_valid = true,
.node = (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
}
};
case OP_MUL: case OP_MUL:
return (NodeResult) {
.is_valid = true,
.node = (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
}
};
case OP_DIV: case OP_DIV:
return (NodeResult) { case OP_POW: {
.is_valid = true, node->type = NODE_BINARY_OP;
.node = (Node) { node->binary.op = token.op;
.type = NODE_BINARY_OP,
.binary.op = token.op, ParserU8Result rbp_result = infix_rbp(*node);
} if (!rbp_result.is_valid) {
return (TreeResult) {
.is_valid = false,
.err = rbp_result.err,
}; };
case OP_POW:
return (NodeResult) {
.is_valid = true,
.node = (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
} }
};
case OP_FACTORIAL: TreeResult right = parse_expr(
return (NodeResult) { slice,
.is_valid = true, arena,
.node = (Node) { rbp_result.num
.type = NODE_UNARY_OP, );
.unary.op = token.op,
if (!right.is_valid) {
return right;
} }
node->binary.left = left;
node->binary.right = right.node;
return (TreeResult) {
.is_valid = true,
.node = node,
}; };
}
// Postfix operators
case OP_FACTORIAL: {
node->type = NODE_UNARY_OP;
node->unary.op = token.op;
node->unary.to = left;
return (TreeResult) {
.is_valid = true,
.node = node,
};
}
default: default:
return (NodeResult) { return (TreeResult) {
.is_valid = false, .is_valid = false,
.err = PARSER_UNEXPECTED_TOKEN, .err = PARSER_UNEXPECTED_TOKEN,
}; };
} }
} }
NodeResult nud(Token token) { TreeResult nud(ArraySlice *slice, Arena *arena, Token token) {
arena_ensure_capacity(
arena,
sizeof(Node),
alignof(Node)
);
Node *node = arena_unwrap_pointer(
arena_alloc(
arena,
sizeof(Node),
alignof(Node)
)
);
if (token.type == TOKEN_INTEGER) { if (token.type == TOKEN_INTEGER) {
return (NodeResult) { node->type = NODE_INT;
node->num = token.num;
return (TreeResult) {
.is_valid = true, .is_valid = true,
.node = (Node) { .node = node,
.type = NODE_INT,
.num = token.num,
}
}; };
} }
switch (token.op) { switch (token.op) {
case OP_START_PAR: case OP_START_PAR: {
return (NodeResult) { TreeResult expr = parse_expr(slice, arena, 0);
.is_valid = true, if (!expr.is_valid) {
.node = (Node) { return expr;
.type = NODE_PARENTHESIS,
.par = token.op,
} }
Token end_par;
if (arrayslice_next(slice, &end_par) != ARRLIST_OK) {
return (TreeResult) {
.is_valid = false,
.err = PARSER_UNMATCHED_PAREN,
}; };
case OP_SUB:
return (NodeResult) {
.is_valid = true,
.node = (Node) {
.type = NODE_UNARY_OP,
.unary.op = token.op,
} }
if (end_par.type != TOKEN_OPERATOR ||
end_par.op != OP_END_PAR) {
return (TreeResult) {
.is_valid = false,
.err = PARSER_UNMATCHED_PAREN,
}; };
}
return expr;
}
case OP_ADD: case OP_ADD:
return (NodeResult) {
.is_valid = true, case OP_SUB: {
.node = (Node) { node->type = NODE_UNARY_OP;
.type = NODE_UNARY_OP, node->unary.op = token.op;
.unary.op = token.op,
} ParserU8Result rbp_result = prefix_rbp(*node);
if (!rbp_result.is_valid) {
return (TreeResult) {
.is_valid = false,
.err = rbp_result.err,
}; };
}
TreeResult right = parse_expr(
slice,
arena,
rbp_result.num
);
if (!right.is_valid) {
return right;
}
node->unary.to = right.node;
return (TreeResult) {
.is_valid = true,
.node = node,
};
}
default: default:
return (NodeResult) { return (TreeResult) {
.is_valid = false, .is_valid = false,
.err = PARSER_UNEXPECTED_TOKEN, .err = PARSER_UNEXPECTED_TOKEN,
}; };
} }
} }
Node token_to_node(Token token) {
if (token.type == TOKEN_INTEGER) {
return (Node) {
.type = NODE_INT,
.num = token.num,
};
}
switch (token.op) {
case OP_ADD:
return (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
};
case OP_SUB:
return (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
};
case OP_MUL:
return (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
};
case OP_DIV:
return (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
};
case OP_POW:
return (Node) {
.type = NODE_BINARY_OP,
.binary.op = token.op,
};
case OP_FACTORIAL:
return (Node) {
.type = NODE_UNARY_OP,
.binary.op = token.op,
};
case OP_START_PAR:
return (Node) {
.type = NODE_PARENTHESIS,
.binary.op = token.op,
};
case OP_END_PAR:
return (Node) {
.type = NODE_PARENTHESIS,
.binary.op = token.op,
};
}
}
ParserResult parse(TokenizeResult tokens) { ParserResult parse(TokenizeResult tokens) {
if (!tokens.is_valid) { if (!tokens.is_valid) {
@@ -309,29 +318,46 @@ ParserResult parse(TokenizeResult tokens) {
} }
TreeResult parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { TreeResult parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) {
arena_ensure_capacity(
arena,
sizeof(Node),
alignof(Node)
); // shouldn't fail but if it does then what a shame
// Get pointer in the arena
Node *left_side = arena_unwrap_pointer(
arena_alloc(
arena,
sizeof(Node),
alignof(Node)
)
);
// convert token to node :)
Token current_token; Token current_token;
arrayslice_next(slice, &current_token);
*left_side = token_to_node(current_token);
if (left_side->type == NODE_PARENTHESIS && if (arrayslice_next(slice, &current_token) != ARRLIST_OK) {
left_side->par == OP_START_PAR) { return (TreeResult) {
TreeResult result = parse_expr(slice, arena, 0); .is_valid = false,
.err = PARSER_UNEXMECTED_EOF,
};
}
TreeResult left_result = nud(slice, arena, current_token);
if (!left_result.is_valid) {
return left_result;
}
Node *left_side = left_result.node;
while (arrayslice_is_valid(slice)) {
Token operator_token;
arrayslice_peek(slice, &operator_token);
if (operator_token.type != TOKEN_OPERATOR) {
break;
}
Node operator_node = {
.type = NODE_BINARY_OP,
.binary.op = operator_token.op,
};
ParserU8Result postfix_lbp_result = postfix_lbp(operator_node);
if (postfix_lbp_result.is_valid) {
if (postfix_lbp_result.num < min_bp) {
break;
}
arrayslice_next(slice, NULL);
TreeResult result = led(slice, arena, left_side, operator_token);
if (!result.is_valid) { if (!result.is_valid) {
return result; return result;
@@ -339,135 +365,29 @@ TreeResult parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) {
left_side = result.node; left_side = result.node;
// We dont really need to convert to node
// parenthesis are there just to change up
// the bp
Token end_par;
arrayslice_next(slice, &end_par);
if (end_par.type != TOKEN_OPERATOR ||
end_par.op != OP_END_PAR) {
return (TreeResult) {
.is_valid = false,
.err = PARSER_UNMATCHED_PAREN,
};
}
return (TreeResult) {
.is_valid = true,
.node = left_side,
};
}
// If prefix
if (left_side->type == NODE_UNARY_OP) {
ParserU8Result rbp_result = prefix_rbp(*left_side);
if (!rbp_result.is_valid) {
return (TreeResult) {
.is_valid = false,
.err = rbp_result.err,
};
}
TreeResult righ_side_result = parse_expr(slice, arena, rbp_result.num);
if (!righ_side_result.is_valid) {
return righ_side_result;
}
left_side->unary.to = righ_side_result.node;
}
while (true) {
if (!arrayslice_is_valid(slice)) {
break;
}
Token operator_token;
arrayslice_peek(slice, &operator_token);
if (operator_token.type != TOKEN_OPERATOR) {
return (TreeResult) {
.is_valid = false,
.err = PARSER_MISSING_OPERAND,
};
}
Node operator_node = token_to_node(operator_token);
// temporary for bad error handling
ParserU8Result postfix_lbp_result = postfix_lbp(operator_node);
if (postfix_lbp_result.is_valid) {
if (postfix_lbp_result.num < min_bp) {
break;
}
// allocate operator
arrayslice_next(slice, NULL);
arena_ensure_capacity(
arena,
sizeof(Node),
alignof(Node));
Node *new_node = arena_unwrap_pointer(
arena_alloc(
arena,
sizeof(Node),
alignof(Node)
)
);
*new_node = operator_node;
new_node->unary.to = left_side;
left_side = new_node;
continue; continue;
} }
ParserU8Result rbp_result = infix_rbp(operator_node); // Path for infix basically
ParserU8Result lbp_result = infix_lbp(operator_node); ParserU8Result lbp_result = infix_lbp(operator_node);
if (!rbp_result.is_valid || !lbp_result.is_valid) {
return (TreeResult) { if (!lbp_result.is_valid) {
.is_valid = false, break;
.err = PARSER_UNEXPECTED_TOKEN,
};
} }
if (rbp_result.is_valid && lbp_result.is_valid) {
// If lbp is LESS then stop recursion,
// we found the next smaller binding power
// or the one with more precedence
if (lbp_result.num < min_bp) { if (lbp_result.num < min_bp) {
break; break;
} }
// If NOT, then we continue wtching ahead
// for the next one but taking our current
// concern that is rbp of the current operator
arrayslice_next(slice, NULL); arrayslice_next(slice, NULL);
TreeResult right_side_result = parse_expr(slice, arena, rbp_result.num);
if (!right_side_result.is_valid) { TreeResult result = led(slice, arena, left_side, operator_token);
return right_side_result;
if (!result.is_valid) {
return result;
} }
arena_ensure_capacity( left_side = result.node;
arena,
sizeof(Node),
alignof(Node));
Node *new_node = arena_unwrap_pointer(
arena_alloc(
arena,
sizeof(Node),
alignof(Node)
)
);
*new_node = operator_node;
new_node->binary.left = left_side;
new_node->binary.right = right_side_result.node;
left_side = new_node;
continue;
}
break;
} }
// Final: return left side // Final: return left side