diff --git a/include/lexer.h b/include/lexer.h index 5081605..387c77c 100644 --- a/include/lexer.h +++ b/include/lexer.h @@ -20,6 +20,7 @@ typedef enum { OP_MUL, OP_DIV, OP_POW, + OP_FACTORIAL, } Operator; typedef enum { diff --git a/src/lexer.c b/src/lexer.c index 201a187..4696fe7 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -155,6 +155,9 @@ Operator char_to_operator(int c) { case '^': return OP_POW; break; + case '!': + return OP_FACTORIAL; + break; default: // I mean shouldn't be used, we assume return -1; } @@ -172,5 +175,9 @@ char operator_to_char(Operator op) { return '/'; case OP_POW: return '^'; + case OP_FACTORIAL: + return '!'; + default: + return EOF; } } diff --git a/src/parser.c b/src/parser.c index 2d956f5..101c995 100644 --- a/src/parser.c +++ b/src/parser.c @@ -14,12 +14,26 @@ uint8_t prefix_rbp(ASTNode node) { switch (node.data.unary.op) { case OP_SUB: case OP_ADD: - return 5; + return 30; default: return -1; } } +uint8_t postfix_lbp(ASTNode node) { + if (node.type == NODE_INTEGER) { + return 0; + } + + switch (node.data.unary.op) { + case OP_FACTORIAL: + return 40; + default: + // needs to be dealt with with resulttypes + return 255; + } +} + uint8_t infix_lbp(ASTNode node) { if (node.type == NODE_INTEGER) { return 0; @@ -34,7 +48,7 @@ uint8_t infix_lbp(ASTNode node) { case OP_MUL: return 20; case OP_POW: - return 31; + return 51; default: return 0; } @@ -54,7 +68,7 @@ uint8_t infix_rbp(ASTNode node) { case OP_MUL: return 21; case OP_POW: - return 30; + return 50; default: return 0; } @@ -107,10 +121,39 @@ ASTNode *parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { break; } + // Here check if not OP error + ASTNode operator; // Here should chekc if is operator not some bs // Third, get operator and binding powers arrayslice_peek(slice, &operator); + + // temporary for bad error handling + if (postfix_lbp(operator) != 255) { + if (postfix_lbp(operator) < min_bp) { + break; + } + + // allocate operator + arrayslice_next(slice, NULL); + arena_ensure_capacity( + arena, + sizeof(ASTNode), + alignof(ASTNode)); + ASTNode *new_node = arena_unwrap_pointer( + arena_alloc( + arena, + sizeof(ASTNode), + alignof(ASTNode) + ) + ); + *new_node = operator; + + + new_node->data.unary.val = left_side; + + left_side = new_node; + } uint8_t rbp = infix_rbp(operator); uint8_t lbp = infix_lbp(operator);