diff --git a/include/lexer.h b/include/lexer.h index 387c77c..4af0f9d 100644 --- a/include/lexer.h +++ b/include/lexer.h @@ -11,6 +11,7 @@ typedef enum { NODE_INTEGER, NODE_BINARY_OP, NODE_UNARY_OP, + NODE_PARENTHESIS, } ASTNodeType; // For classify operators @@ -21,6 +22,8 @@ typedef enum { OP_DIV, OP_POW, OP_FACTORIAL, + OP_START_PAR, + OP_END_PAR, } Operator; typedef enum { @@ -46,6 +49,10 @@ typedef struct ASTNode { struct ASTNode *val; Operator op; } unary; + struct { + struct ASTNode *val; + Operator op; + } parenthesis; } data; } ASTNode; diff --git a/src/lexer.c b/src/lexer.c index 4696fe7..2115cc4 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -132,6 +132,9 @@ bool isoperator(int c) { case '/': case '*': case '^': + case '!': + case '(': + case ')': return true; default: return false; @@ -158,6 +161,12 @@ Operator char_to_operator(int c) { case '!': return OP_FACTORIAL; break; + case '(': + return OP_START_PAR; + break; + case ')': + return OP_END_PAR; + break; default: // I mean shouldn't be used, we assume return -1; } @@ -177,6 +186,10 @@ char operator_to_char(Operator op) { return '^'; case OP_FACTORIAL: return '!'; + case OP_START_PAR: + return '('; + case OP_END_PAR: + return ')'; default: return EOF; } diff --git a/src/parser.c b/src/parser.c index 101c995..2a09988 100644 --- a/src/parser.c +++ b/src/parser.c @@ -101,6 +101,20 @@ ASTNode *parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { ) ); + arrayslice_next(slice, left_side); + + if (left_side->type == NODE_PARENTHESIS && + left_side->data.parenthesis.op == OP_START_PAR) { + left_side = parse_expr(slice, arena, 0); + // HERE CHEKC LATER if slice.next != ')' + ASTNode *end_par; + arrayslice_next(slice, &end_par); + if (end_par->type != NODE_PARENTHESIS || + end_par->data.parenthesis.op != OP_END_PAR) { + // todo + } + return left_side; + } // if is unary then take prefix bp and continue // to the right, no need to allocate left side // because we just did and right side @@ -110,10 +124,7 @@ ASTNode *parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { ASTNode *righ_side = parse_expr(slice, arena, rbp); left_side->data.unary.val = righ_side; - return left_side; } - // Should check if is Integer or number - arrayslice_next(slice, left_side); while (true) { // Second: Get next one and checn bp @@ -153,47 +164,54 @@ ASTNode *parse_expr(ArraySlice *slice, Arena *arena, uint8_t min_bp) { new_node->data.unary.val = left_side; left_side = new_node; + continue; } + + // check if it has infix or not, if not then error uint8_t rbp = infix_rbp(operator); uint8_t lbp = infix_lbp(operator); - // If lbp is LESS then stop recursion, - // we found the next smaller binding power - // or the one with more precedence - if (lbp < min_bp) { - break; + if (rbp != 255 && lbp != 255) { + + // If lbp is LESS then stop recursion, + // we found the next smaller binding power + // or the one with more precedence + if (lbp < min_bp) { + 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); + ASTNode *right_side = parse_expr(slice, arena, rbp); + + 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.binary.left = left_side; + new_node->data.binary.right = right_side; + + left_side = new_node; + + continue; } - - // 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); - ASTNode *right_side = parse_expr(slice, arena, rbp); - - 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.binary.left = left_side; - new_node->data.binary.right = right_side; - - left_side = new_node; + break; } // Final: return left side return left_side; } - - -