refactor-lexer #11
@@ -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;
|
||||
|
||||
|
||||
13
src/lexer.c
13
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;
|
||||
}
|
||||
|
||||
88
src/parser.c
88
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user