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:
@@ -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);
|
||||||
|
|||||||
440
src/parser.c
440
src/parser.c
@@ -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, ¤t_token);
|
|
||||||
*left_side = token_to_node(current_token);
|
|
||||||
|
|
||||||
if (left_side->type == NODE_PARENTHESIS &&
|
if (arrayslice_next(slice, ¤t_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
|
||||||
|
|||||||
Reference in New Issue
Block a user