284 lines
7.0 KiB
C
284 lines
7.0 KiB
C
function Expr* parse_expr(Parser* p);
|
|
function Expr* parse_list_expr(Parser* p);
|
|
|
|
function Expr*
|
|
parse_atom_expr(Parser* p){
|
|
Expr* result = 0;
|
|
if (token_is(p, TK_Identifier) ||
|
|
token_is(p, TK_StringLit) ||
|
|
token_is(p, TK_U8Lit) ||
|
|
token_is(p, TK_Int)){
|
|
result = expr_atom(p, token_next(p));
|
|
}
|
|
else if (token_match(p, TK_OpenParen)){
|
|
result = parse_list_expr(p);
|
|
token_expect(p, TK_CloseParen);
|
|
}
|
|
else {
|
|
parser_push_error(p, token_next(p), "Invalid expression token");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function Expr*
|
|
parse_postfix_expr(Parser* p){
|
|
Expr* result = parse_atom_expr(p);
|
|
while (token_is(p, TK_Dot)
|
|
|| token_is(p, TK_Arrow)
|
|
|| token_is(p, TK_DoubleColon)
|
|
|| token_is(p, TK_OpenParen)
|
|
|| token_is(p, TK_OpenBracket)
|
|
|| token_is(p, TK_Decrement)
|
|
|| token_is(p, TK_Increment)){
|
|
Token *op = token_get(p);
|
|
|
|
if (token_match(p, TK_Arrow)
|
|
|| token_match(p, TK_DoubleColon)
|
|
|| token_match(p, TK_Dot)){
|
|
Expr* r = parse_atom_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
|
|
else if (token_match(p, TK_OpenParen)){
|
|
Expr* list = 0;
|
|
if (!token_match(p, TK_CloseParen)){
|
|
list = parse_list_expr(p);
|
|
token_expect(p, TK_CloseParen);
|
|
}
|
|
result = expr_call(p, op, result, list);
|
|
}
|
|
|
|
else if (token_match(p, TK_OpenBracket)){
|
|
Expr* list = 0;
|
|
if (!token_match(p, TK_CloseBracket)){
|
|
list = parse_list_expr(p);
|
|
token_match(p, TK_CloseBracket);
|
|
}
|
|
result = expr_index(p, op, result, list);
|
|
}
|
|
|
|
else {
|
|
assert(op->kind == TK_Increment || op->kind == TK_Decrement);
|
|
token_next(p);
|
|
if (op->kind == TK_Increment) op->kind = TK_PostIncrement;
|
|
else if (op->kind == TK_Decrement) op->kind = TK_PostDecrement;
|
|
result = expr_unary(p, op, result);
|
|
}
|
|
|
|
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_unary_expr(Parser* p) {
|
|
Expr* result = 0;
|
|
if (token_is(p, TK_Sub)
|
|
|| token_is(p, TK_Add)
|
|
|| token_is(p, TK_Mul)
|
|
|| token_is(p, TK_BitAnd)
|
|
|| token_is(p, TK_Not)
|
|
|| token_is(p, TK_Neg)
|
|
|| token_is(p, TK_Increment)
|
|
|| token_is(p, TK_Decrement)) {
|
|
Token *op = token_next(p);
|
|
result = parse_unary_expr(p);
|
|
result = expr_unary(p, op, result);
|
|
}
|
|
else if (token_is_keyword(p, keyword_sizeof)) {
|
|
Token *token = token_next(p);
|
|
result = parse_unary_expr(p);
|
|
result = expr_unary(p, token, result);
|
|
}
|
|
else if (token_is(p, TK_OpenParen)) { // cast requires lookahead
|
|
Token *token = token_peek(p, 1);
|
|
if (token->kind == TK_Keyword || token->kind == TK_Identifier) {
|
|
|
|
AST_Node *type = symbol_lookup_type(p, token->intern_val);
|
|
if(type){
|
|
token_next(p);
|
|
token_next(p);
|
|
// @Todo(Krzosa): Parse pointer types
|
|
token_expect(p, TK_CloseParen);
|
|
result = parse_unary_expr(p);
|
|
result = expr_cast(p, token, type, result);
|
|
}
|
|
else {
|
|
result = parse_postfix_expr(p);
|
|
}
|
|
|
|
}
|
|
else {
|
|
result = parse_postfix_expr(p);
|
|
}
|
|
}
|
|
else {
|
|
result = parse_postfix_expr(p);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_mul_expr(Parser* p) {
|
|
Expr* result = parse_unary_expr(p);
|
|
while (token_is(p, TK_Mul)
|
|
|| token_is(p, TK_Div)
|
|
|| token_is(p, TK_Mod)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_unary_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_add_expr(Parser* p) {
|
|
Expr* result = parse_mul_expr(p);
|
|
while (token_is(p, TK_Add)
|
|
|| token_is(p, TK_Sub)) {
|
|
Token *op = token_next(p);
|
|
Expr* right = parse_mul_expr(p);
|
|
result = expr_binary(p, op, result, right);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_shift_expr(Parser* p) {
|
|
Expr* result = parse_add_expr(p);
|
|
while (token_is(p, TK_RightShift)
|
|
|| token_is(p, TK_LeftShift)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_add_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_compare_expr(Parser* p) {
|
|
Expr* result = parse_shift_expr(p);
|
|
while (token_is(p, TK_LesserThen)
|
|
|| token_is(p, TK_GreaterThen)
|
|
|| token_is(p, TK_LesserThenOrEqual)
|
|
|| token_is(p, TK_GreaterThenOrEqual)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_shift_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_equality_expr(Parser* p) {
|
|
Expr* result = parse_compare_expr(p);
|
|
while (token_is(p, TK_Equals)
|
|
|| token_is(p, TK_NotEquals)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_compare_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_bit_and_expr(Parser* p) {
|
|
Expr* result = parse_equality_expr(p);
|
|
while (token_is(p, TK_BitAnd)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_equality_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_bit_xor_expr(Parser* p) {
|
|
Expr* result = parse_bit_and_expr(p);
|
|
while (token_is(p, TK_BitXor)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_bit_and_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_bit_or_expr(Parser* p) {
|
|
Expr* result = parse_bit_xor_expr(p);
|
|
while (token_is(p, TK_BitOr)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_bit_xor_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_and_expr(Parser* p) {
|
|
Expr* result = parse_bit_or_expr(p);
|
|
while (token_is(p, TK_And)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_bit_or_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_or_expr(Parser* p) {
|
|
Expr* result = parse_and_expr(p);
|
|
while (token_is(p, TK_Or)) {
|
|
Token *op = token_next(p);
|
|
Expr* r = parse_and_expr(p);
|
|
result = expr_binary(p, op, result, r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_ternary_expr(Parser* p) {
|
|
Expr* result = parse_or_expr(p);
|
|
if (token_is(p, TK_Question)) {
|
|
Token *token = token_next(p);
|
|
Expr* on_true = parse_ternary_expr(p);
|
|
token_expect(p, TK_Colon);
|
|
Expr* on_false = parse_ternary_expr(p);
|
|
result = expr_ternary(p, token, result, on_true, on_false);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_assign_expr(Parser* p) {
|
|
Expr* result = parse_ternary_expr(p);
|
|
if (token_is_assignment(p)) {
|
|
Token *op = token_next(p);
|
|
Expr* right = parse_assign_expr(p);
|
|
result = expr_binary(p, op, result, right);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function
|
|
Expr* parse_list_expr(Parser* p) {
|
|
Expr* result = parse_assign_expr(p);
|
|
if (token_is(p, TK_Comma)) {
|
|
Expr *list = expr_list(p, token_get(p));
|
|
expr_list_push(list, result);
|
|
result = list;
|
|
}
|
|
while (token_is(p, TK_Comma)) {
|
|
Token *token = token_next(p);
|
|
Expr* expr = parse_assign_expr(p);
|
|
expr_list_push(result, expr);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function Expr*
|
|
parse_expr(Parser* p) {
|
|
return parse_assign_expr(p);
|
|
}
|