parent
38f12adbda
commit
64dd0b8d95
@ -92,7 +92,7 @@ AssignmentExpression : BoolOrExpression token(Equal) BoolOrExpression | BoolOrEx
|
||||
|
||||
BlockExpression : IfExpression | Block
|
||||
|
||||
BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndExpression
|
||||
BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
|
||||
|
||||
ReturnExpression : token(Return) option(Expression)
|
||||
|
||||
@ -102,33 +102,33 @@ ElseIf : token(Else) IfExpression
|
||||
|
||||
Else : token(Else) Block
|
||||
|
||||
BoolAndExpression : ComparisonExpression token(BoolAnd) ComparisonExpression | ComparisonExpression
|
||||
BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression
|
||||
|
||||
ComparisonExpression : BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression
|
||||
|
||||
ComparisonOperator : token(BoolEq) | token(BoolNotEq) | token(BoolLessThan) | token(BoolGreaterThan) | token(BoolLessEqual) | token(BoolGreaterEqual)
|
||||
|
||||
BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryXorExpression | BinaryXorExpression
|
||||
BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryOrExpression | BinaryXorExpression
|
||||
|
||||
BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryAndExpression | BinaryAndExpression
|
||||
BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryXorExpression | BinaryAndExpression
|
||||
|
||||
BinaryAndExpression : BitShiftExpression token(BinAnd) BitShiftExpression | BitShiftExpression
|
||||
BinaryAndExpression : BitShiftExpression token(BinAnd) BinaryAndExpression | BitShiftExpression
|
||||
|
||||
BitShiftExpression : AdditionExpression BitShiftOperator AdditionExpression | AdditionExpression
|
||||
BitShiftExpression : AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
|
||||
|
||||
BitShiftOperator : token(BitShiftLeft | token(BitShiftRight)
|
||||
BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight)
|
||||
|
||||
AdditionExpression : MultiplyExpression AdditionOperator MultiplyExpression | MultiplyExpression
|
||||
AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
|
||||
|
||||
AdditionOperator : token(Plus) | token(Minus)
|
||||
|
||||
MultiplyExpression : CastExpression MultiplyOperator CastExpression | CastExpression
|
||||
MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression
|
||||
|
||||
MultiplyOperator : token(Star) | token(Slash) | token(Percent)
|
||||
|
||||
CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression
|
||||
CastExpression : CastExpression token(as) Type | PrefixOpExpression
|
||||
|
||||
PrefixOpExpression : PrefixOp SuffixOpExpression | SuffixOpExpression
|
||||
PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
|
||||
|
||||
SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression)
|
||||
|
||||
|
@ -894,20 +894,24 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
return_type = g->builtin_types.entry_bool;
|
||||
break;
|
||||
case BinOpTypeBinOr:
|
||||
zig_panic("TODO bin or type");
|
||||
break;
|
||||
case BinOpTypeBinXor:
|
||||
zig_panic("TODO bin xor type");
|
||||
break;
|
||||
case BinOpTypeBinAnd:
|
||||
zig_panic("TODO bin and type");
|
||||
break;
|
||||
{
|
||||
// TODO: don't require i32
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1);
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2);
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
}
|
||||
case BinOpTypeBitShiftLeft:
|
||||
zig_panic("TODO bit shift left type");
|
||||
break;
|
||||
case BinOpTypeBitShiftRight:
|
||||
zig_panic("TODO bit shift right type");
|
||||
break;
|
||||
{
|
||||
// TODO: don't require i32
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1);
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2);
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
}
|
||||
case BinOpTypeAdd:
|
||||
case BinOpTypeSub:
|
||||
// TODO think how should type checking for these work?
|
||||
@ -918,14 +922,15 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
case BinOpTypeMult:
|
||||
zig_panic("TODO mult type");
|
||||
break;
|
||||
case BinOpTypeDiv:
|
||||
zig_panic("TODO div type");
|
||||
break;
|
||||
case BinOpTypeMod:
|
||||
zig_panic("TODO modulus type");
|
||||
break;
|
||||
{
|
||||
// TODO: don't require i32
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1);
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2);
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
}
|
||||
case BinOpTypeInvalid:
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -1081,11 +1086,19 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
return_type = g->builtin_types.entry_bool;
|
||||
break;
|
||||
case PrefixOpBinNot:
|
||||
zig_panic("TODO type check bin not");
|
||||
break;
|
||||
{
|
||||
// TODO: don't require i32
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.prefix_op_expr.primary_expr);
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
}
|
||||
case PrefixOpNegation:
|
||||
zig_panic("TODO type check negation");
|
||||
break;
|
||||
{
|
||||
// TODO: don't require i32
|
||||
analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.prefix_op_expr.primary_expr);
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
}
|
||||
case PrefixOpInvalid:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -485,22 +485,18 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
|
||||
// block for when val1 == false (don't even evaluate the second part)
|
||||
LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");
|
||||
|
||||
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(val1));
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef val1_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, zero, "");
|
||||
LLVMBuildCondBr(g->builder, val1_i1, false_block, true_block);
|
||||
LLVMBuildCondBr(g->builder, val1, true_block, false_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, true_block);
|
||||
LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef val2_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
|
||||
LLVMBuildBr(g->builder, false_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, false_block);
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
|
||||
LLVMValueRef one_i1 = LLVMConstAllOnes(LLVMInt1Type());
|
||||
LLVMValueRef incoming_values[2] = {one_i1, val2_i1};
|
||||
LLVMValueRef incoming_values[2] = {val1, val2};
|
||||
LLVMBasicBlockRef incoming_blocks[2] = {orig_block, true_block};
|
||||
LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
|
||||
|
||||
@ -519,22 +515,18 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
|
||||
// block for when val1 == true (don't even evaluate the second part)
|
||||
LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");
|
||||
|
||||
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(val1));
|
||||
add_debug_source_node(g, expr_node);
|
||||
LLVMValueRef val1_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, zero, "");
|
||||
LLVMBuildCondBr(g->builder, val1_i1, false_block, true_block);
|
||||
LLVMBuildCondBr(g->builder, val1, true_block, false_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, false_block);
|
||||
LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2);
|
||||
add_debug_source_node(g, expr_node);
|
||||
LLVMValueRef val2_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
|
||||
LLVMBuildBr(g->builder, true_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, true_block);
|
||||
add_debug_source_node(g, expr_node);
|
||||
LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
|
||||
LLVMValueRef one_i1 = LLVMConstAllOnes(LLVMInt1Type());
|
||||
LLVMValueRef incoming_values[2] = {one_i1, val2_i1};
|
||||
LLVMValueRef incoming_values[2] = {val1, val2};
|
||||
LLVMBasicBlockRef incoming_blocks[2] = {orig_block, false_block};
|
||||
LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
|
||||
|
||||
|
222
src/parser.cpp
222
src/parser.cpp
@ -944,7 +944,7 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man
|
||||
}
|
||||
|
||||
/*
|
||||
PrefixOpExpression : PrefixOp SuffixOpExpression | SuffixOpExpression
|
||||
PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
|
||||
*/
|
||||
static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
@ -952,7 +952,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo
|
||||
if (prefix_op == PrefixOpInvalid)
|
||||
return ast_parse_suffix_op_expr(pc, token_index, mandatory);
|
||||
|
||||
AstNode *prefix_op_expr = ast_parse_suffix_op_expr(pc, token_index, true);
|
||||
AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
|
||||
node->data.prefix_op_expr.primary_expr = prefix_op_expr;
|
||||
node->data.prefix_op_expr.prefix_op = prefix_op;
|
||||
@ -962,24 +962,26 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo
|
||||
|
||||
|
||||
/*
|
||||
CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression
|
||||
CastExpression : CastExpression token(as) Type | PrefixOpExpression
|
||||
*/
|
||||
static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory);
|
||||
if (!prefix_op_expr)
|
||||
AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *as_kw = &pc->tokens->at(*token_index);
|
||||
if (as_kw->id != TokenIdKeywordAs)
|
||||
return prefix_op_expr;
|
||||
*token_index += 1;
|
||||
while (true) {
|
||||
Token *as_kw = &pc->tokens->at(*token_index);
|
||||
if (as_kw->id != TokenIdKeywordAs)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw);
|
||||
node->data.cast_expr.expr = prefix_op_expr;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw);
|
||||
node->data.cast_expr.expr = operand_1;
|
||||
|
||||
node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index);
|
||||
node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index);
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
static BinOpType tok_to_mult_op(Token *token) {
|
||||
@ -1009,26 +1011,28 @@ static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mand
|
||||
}
|
||||
|
||||
/*
|
||||
MultiplyExpression : CastExpression MultiplyOperator CastExpression | CastExpression
|
||||
MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression
|
||||
*/
|
||||
static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_cast_expression(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
BinOpType mult_op = ast_parse_mult_op(pc, token_index, false);
|
||||
if (mult_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
BinOpType mult_op = ast_parse_mult_op(pc, token_index, false);
|
||||
if (mult_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_cast_expression(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_cast_expression(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = mult_op;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = mult_op;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
static BinOpType tok_to_add_op(Token *token) {
|
||||
@ -1057,26 +1061,28 @@ static BinOpType ast_parse_add_op(ParseContext *pc, int *token_index, bool manda
|
||||
}
|
||||
|
||||
/*
|
||||
AdditionExpression : MultiplyExpression AdditionOperator MultiplyExpression | MultiplyExpression
|
||||
AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
|
||||
*/
|
||||
static AstNode *ast_parse_add_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_mult_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
BinOpType add_op = ast_parse_add_op(pc, token_index, false);
|
||||
if (add_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
BinOpType add_op = ast_parse_add_op(pc, token_index, false);
|
||||
if (add_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_mult_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_mult_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = add_op;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = add_op;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
static BinOpType tok_to_bit_shift_op(Token *token) {
|
||||
@ -1088,7 +1094,7 @@ static BinOpType tok_to_bit_shift_op(Token *token) {
|
||||
}
|
||||
|
||||
/*
|
||||
BitShiftOperator : token(BitShiftLeft | token(BitShiftRight)
|
||||
BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight)
|
||||
*/
|
||||
static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
@ -1105,96 +1111,104 @@ static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool
|
||||
}
|
||||
|
||||
/*
|
||||
BitShiftExpression : AdditionExpression BitShiftOperator AdditionExpression | AdditionExpression
|
||||
BitShiftExpression : AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
|
||||
*/
|
||||
static AstNode *ast_parse_bit_shift_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_add_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
BinOpType bit_shift_op = ast_parse_bit_shift_op(pc, token_index, false);
|
||||
if (bit_shift_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
BinOpType bit_shift_op = ast_parse_bit_shift_op(pc, token_index, false);
|
||||
if (bit_shift_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_add_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_add_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = bit_shift_op;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = bit_shift_op;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
BinaryAndExpression : BitShiftExpression token(BinAnd) BitShiftExpression | BitShiftExpression
|
||||
BinaryAndExpression : BitShiftExpression token(BinAnd) BinaryAndExpression | BitShiftExpression
|
||||
*/
|
||||
static AstNode *ast_parse_bin_and_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_bit_shift_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBinAnd)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBinAnd)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_bit_shift_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_bit_shift_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBinAnd;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBinAnd;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryAndExpression | BinaryAndExpression
|
||||
BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryXorExpression | BinaryAndExpression
|
||||
*/
|
||||
static AstNode *ast_parse_bin_xor_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_bin_and_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBinXor)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBinXor)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_bin_and_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_bin_and_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBinXor;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBinXor;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryXorExpression | BinaryXorExpression
|
||||
BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryOrExpression | BinaryXorExpression
|
||||
*/
|
||||
static AstNode *ast_parse_bin_or_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_bin_xor_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBinOr)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBinOr)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_bin_xor_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_bin_xor_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBinOr;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBinOr;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
static BinOpType tok_to_cmp_op(Token *token) {
|
||||
@ -1247,26 +1261,28 @@ static AstNode *ast_parse_comparison_expr(ParseContext *pc, int *token_index, bo
|
||||
}
|
||||
|
||||
/*
|
||||
BoolAndExpression : ComparisonExpression token(BoolAnd) ComparisonExpression | ComparisonExpression
|
||||
BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression
|
||||
*/
|
||||
static AstNode *ast_parse_bool_and_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_comparison_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBoolAnd)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBoolAnd)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_comparison_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_comparison_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBoolAnd;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBoolAnd;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1382,26 +1398,28 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
|
||||
}
|
||||
|
||||
/*
|
||||
BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndExpression
|
||||
BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
|
||||
*/
|
||||
static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_bool_and_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBoolOr)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
while (true) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id != TokenIdBoolOr)
|
||||
return operand_1;
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_bool_and_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_bool_and_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBoolOr;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
node->data.bin_op_expr.bin_op = BinOpTypeBoolOr;
|
||||
node->data.bin_op_expr.op2 = operand_2;
|
||||
|
||||
return node;
|
||||
operand_1 = node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -478,9 +478,10 @@ void tokenize(Buf *buf, Tokenization *out) {
|
||||
t.multi_line_comment_count = 1;
|
||||
break;
|
||||
default:
|
||||
t.pos -= 1;
|
||||
end_token(&t);
|
||||
t.state = TokenizeStateStart;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case TokenizeStateLineComment:
|
||||
@ -592,9 +593,10 @@ void tokenize(Buf *buf, Tokenization *out) {
|
||||
t.state = TokenizeStateStart;
|
||||
break;
|
||||
default:
|
||||
t.pos -= 1;
|
||||
end_token(&t);
|
||||
t.state = TokenizeStateStart;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -409,6 +409,27 @@ export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 {
|
||||
)SOURCE", "Hello, world!\n");
|
||||
|
||||
|
||||
add_simple_case("a + b + c", R"SOURCE(
|
||||
use "std.zig";
|
||||
|
||||
export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 {
|
||||
if false || false || false { print_str("BAD 1\n" as string); }
|
||||
if true && true && false { print_str("BAD 2\n" as string); }
|
||||
if 1 | 2 | 4 != 7 { print_str("BAD 3\n" as string); }
|
||||
if 3 ^ 6 ^ 8 != 13 { print_str("BAD 4\n" as string); }
|
||||
if 7 & 14 & 28 != 4 { print_str("BAD 5\n" as string); }
|
||||
if 9 << 1 << 2 != 9 << 3 { print_str("BAD 6\n" as string); }
|
||||
if 90 >> 1 >> 2 != 90 >> 3 { print_str("BAD 7\n" as string); }
|
||||
if 100 - 1 + 1000 != 1099 { print_str("BAD 8\n" as string); }
|
||||
if 5 * 4 / 2 % 3 != 1 { print_str("BAD 9\n" as string); }
|
||||
if 5 as i32 as i32 != 5 { print_str("BAD 10\n" as string); }
|
||||
if !!false { print_str("BAD 11\n" as string); }
|
||||
if 7 != --7 { print_str("BAD 12\n" as string); }
|
||||
|
||||
print_str("OK\n" as string);
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user