Commit 64dd0b8d95
Changed files (6)
doc/langref.md
@@ -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)
src/analyze.cpp
@@ -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();
}
src/codegen.cpp
@@ -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);
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;
+ }
}
/*
src/tokenizer.cpp
@@ -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;
}
test/run_tests.cpp
@@ -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");
}