add switch statement support to parser
This commit is contained in:
parent
17e574fec6
commit
c17309dbc5
@ -94,7 +94,7 @@ BlockExpression : IfExpression | Block | WhileExpression | ForExpression | Switc
|
|||||||
|
|
||||||
SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
|
SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
|
||||||
|
|
||||||
SwitchProng : (list(SwitchItem, ",") | "else") option("(" "Symbol" ")") "=>" Expression ","
|
SwitchProng : (list(SwitchItem, ",") | "else") option("," "(" "Symbol" ")") "=>" Expression ","
|
||||||
|
|
||||||
SwitchItem : Expression | (Expression "..." Expression)
|
SwitchItem : Expression | (Expression "..." Expression)
|
||||||
|
|
||||||
|
@ -139,6 +139,9 @@ enum NodeType {
|
|||||||
NodeTypeIfVarExpr,
|
NodeTypeIfVarExpr,
|
||||||
NodeTypeWhileExpr,
|
NodeTypeWhileExpr,
|
||||||
NodeTypeForExpr,
|
NodeTypeForExpr,
|
||||||
|
NodeTypeSwitchExpr,
|
||||||
|
NodeTypeSwitchProng,
|
||||||
|
NodeTypeSwitchRange,
|
||||||
NodeTypeLabel,
|
NodeTypeLabel,
|
||||||
NodeTypeGoto,
|
NodeTypeGoto,
|
||||||
NodeTypeBreak,
|
NodeTypeBreak,
|
||||||
@ -411,6 +414,25 @@ struct AstNodeForExpr {
|
|||||||
VariableTableEntry *index_var;
|
VariableTableEntry *index_var;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstNodeSwitchExpr {
|
||||||
|
AstNode *expr;
|
||||||
|
ZigList<AstNode *> prongs;
|
||||||
|
|
||||||
|
// populated by semantic analyzer
|
||||||
|
Expr resolved_expr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AstNodeSwitchProng {
|
||||||
|
ZigList<AstNode *> items;
|
||||||
|
AstNode *var_symbol;
|
||||||
|
AstNode *expr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AstNodeSwitchRange {
|
||||||
|
AstNode *start;
|
||||||
|
AstNode *end;
|
||||||
|
};
|
||||||
|
|
||||||
struct AstNodeLabel {
|
struct AstNodeLabel {
|
||||||
Buf name;
|
Buf name;
|
||||||
|
|
||||||
@ -623,6 +645,9 @@ struct AstNode {
|
|||||||
AstNodeIfVarExpr if_var_expr;
|
AstNodeIfVarExpr if_var_expr;
|
||||||
AstNodeWhileExpr while_expr;
|
AstNodeWhileExpr while_expr;
|
||||||
AstNodeForExpr for_expr;
|
AstNodeForExpr for_expr;
|
||||||
|
AstNodeSwitchExpr switch_expr;
|
||||||
|
AstNodeSwitchProng switch_prong;
|
||||||
|
AstNodeSwitchRange switch_range;
|
||||||
AstNodeLabel label;
|
AstNodeLabel label;
|
||||||
AstNodeGoto goto_expr;
|
AstNodeGoto goto_expr;
|
||||||
AstNodeAsmExpr asm_expr;
|
AstNodeAsmExpr asm_expr;
|
||||||
|
@ -30,6 +30,8 @@ static AstNode *first_executing_node(AstNode *node) {
|
|||||||
return first_executing_node(node->data.slice_expr.array_ref_expr);
|
return first_executing_node(node->data.slice_expr.array_ref_expr);
|
||||||
case NodeTypeFieldAccessExpr:
|
case NodeTypeFieldAccessExpr:
|
||||||
return first_executing_node(node->data.field_access_expr.struct_expr);
|
return first_executing_node(node->data.field_access_expr.struct_expr);
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
|
return first_executing_node(node->data.switch_range.start);
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeRootExportDecl:
|
case NodeTypeRootExportDecl:
|
||||||
case NodeTypeFnProto:
|
case NodeTypeFnProto:
|
||||||
@ -61,6 +63,8 @@ static AstNode *first_executing_node(AstNode *node) {
|
|||||||
case NodeTypeStructValueField:
|
case NodeTypeStructValueField:
|
||||||
case NodeTypeWhileExpr:
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
case NodeTypeContainerInitExpr:
|
case NodeTypeContainerInitExpr:
|
||||||
case NodeTypeArrayType:
|
case NodeTypeArrayType:
|
||||||
return node;
|
return node;
|
||||||
@ -943,6 +947,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
|||||||
case NodeTypeIfVarExpr:
|
case NodeTypeIfVarExpr:
|
||||||
case NodeTypeWhileExpr:
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
case NodeTypeBreak:
|
case NodeTypeBreak:
|
||||||
@ -3007,6 +3014,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
|
|||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
|
TypeTableEntry *expected_type, AstNode *node)
|
||||||
|
{
|
||||||
|
zig_panic("TODO analyze_switch_expr");
|
||||||
|
}
|
||||||
|
|
||||||
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node)
|
TypeTableEntry *expected_type, AstNode *node)
|
||||||
{
|
{
|
||||||
@ -3184,6 +3197,11 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
|||||||
case NodeTypeArrayType:
|
case NodeTypeArrayType:
|
||||||
return_type = analyze_array_type(g, import, context, expected_type, node);
|
return_type = analyze_array_type(g, import, context, expected_type, node);
|
||||||
break;
|
break;
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
return_type = analyze_switch_expr(g, import, context, expected_type, node);
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeDirective:
|
case NodeTypeDirective:
|
||||||
case NodeTypeFnDecl:
|
case NodeTypeFnDecl:
|
||||||
case NodeTypeFnProto:
|
case NodeTypeFnProto:
|
||||||
@ -3338,6 +3356,9 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
|||||||
case NodeTypeIfVarExpr:
|
case NodeTypeIfVarExpr:
|
||||||
case NodeTypeWhileExpr:
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
case NodeTypeBreak:
|
case NodeTypeBreak:
|
||||||
@ -3472,6 +3493,24 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
|
|||||||
}
|
}
|
||||||
collect_expr_decl_deps(g, import, node->data.array_type.child_type, decl_node);
|
collect_expr_decl_deps(g, import, node->data.array_type.child_type, decl_node);
|
||||||
break;
|
break;
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
collect_expr_decl_deps(g, import, node->data.switch_expr.expr, decl_node);
|
||||||
|
for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
|
||||||
|
AstNode *prong = node->data.switch_expr.prongs.at(i);
|
||||||
|
collect_expr_decl_deps(g, import, prong, decl_node);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
|
||||||
|
AstNode *child = node->data.switch_prong.items.at(i);
|
||||||
|
collect_expr_decl_deps(g, import, child, decl_node);
|
||||||
|
}
|
||||||
|
collect_expr_decl_deps(g, import, node->data.switch_prong.expr, decl_node);
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
|
collect_expr_decl_deps(g, import, node->data.switch_range.start, decl_node);
|
||||||
|
collect_expr_decl_deps(g, import, node->data.switch_range.end, decl_node);
|
||||||
|
break;
|
||||||
case NodeTypeVariableDeclaration:
|
case NodeTypeVariableDeclaration:
|
||||||
case NodeTypeFnProto:
|
case NodeTypeFnProto:
|
||||||
case NodeTypeExternBlock:
|
case NodeTypeExternBlock:
|
||||||
@ -3661,6 +3700,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
|
|||||||
case NodeTypeIfVarExpr:
|
case NodeTypeIfVarExpr:
|
||||||
case NodeTypeWhileExpr:
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
case NodeTypeBreak:
|
case NodeTypeBreak:
|
||||||
@ -3869,6 +3911,10 @@ Expr *get_resolved_expr(AstNode *node) {
|
|||||||
return &node->data.label.resolved_expr;
|
return &node->data.label.resolved_expr;
|
||||||
case NodeTypeArrayType:
|
case NodeTypeArrayType:
|
||||||
return &node->data.array_type.resolved_expr;
|
return &node->data.array_type.resolved_expr;
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
return &node->data.switch_expr.resolved_expr;
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeRootExportDecl:
|
case NodeTypeRootExportDecl:
|
||||||
case NodeTypeFnProto:
|
case NodeTypeFnProto:
|
||||||
@ -3902,6 +3948,9 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
|
|||||||
case NodeTypeIfVarExpr:
|
case NodeTypeIfVarExpr:
|
||||||
case NodeTypeWhileExpr:
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeAsmExpr:
|
case NodeTypeAsmExpr:
|
||||||
case NodeTypeContainerInitExpr:
|
case NodeTypeContainerInitExpr:
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
@ -3953,6 +4002,9 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
|
|||||||
case NodeTypeIfVarExpr:
|
case NodeTypeIfVarExpr:
|
||||||
case NodeTypeWhileExpr:
|
case NodeTypeWhileExpr:
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
case NodeTypeAsmExpr:
|
case NodeTypeAsmExpr:
|
||||||
case NodeTypeContainerInitExpr:
|
case NodeTypeContainerInitExpr:
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
|
@ -1965,6 +1965,12 @@ static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
|
|||||||
return fn_entry->fn_value;
|
return fn_entry->fn_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
|
||||||
|
assert(node->type == NodeTypeSwitchExpr);
|
||||||
|
|
||||||
|
zig_panic("TODO gen_switch_expr");
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
@ -2040,6 +2046,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
|||||||
}
|
}
|
||||||
case NodeTypeContainerInitExpr:
|
case NodeTypeContainerInitExpr:
|
||||||
return gen_container_init_expr(g, node);
|
return gen_container_init_expr(g, node);
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
return gen_switch_expr(g, node);
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeRootExportDecl:
|
case NodeTypeRootExportDecl:
|
||||||
case NodeTypeFnProto:
|
case NodeTypeFnProto:
|
||||||
@ -2053,6 +2061,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
|||||||
case NodeTypeStructField:
|
case NodeTypeStructField:
|
||||||
case NodeTypeStructValueField:
|
case NodeTypeStructValueField:
|
||||||
case NodeTypeArrayType:
|
case NodeTypeArrayType:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
117
src/parser.cpp
117
src/parser.cpp
@ -123,6 +123,12 @@ const char *node_type_str(NodeType node_type) {
|
|||||||
return "WhileExpr";
|
return "WhileExpr";
|
||||||
case NodeTypeForExpr:
|
case NodeTypeForExpr:
|
||||||
return "ForExpr";
|
return "ForExpr";
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
return "SwitchExpr";
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
return "SwitchProng";
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
|
return "SwitchRange";
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
return "Label";
|
return "Label";
|
||||||
case NodeTypeGoto:
|
case NodeTypeGoto:
|
||||||
@ -342,6 +348,30 @@ void ast_print(AstNode *node, int indent) {
|
|||||||
}
|
}
|
||||||
ast_print(node->data.for_expr.body, indent + 2);
|
ast_print(node->data.for_expr.body, indent + 2);
|
||||||
break;
|
break;
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||||
|
ast_print(node->data.switch_expr.expr, indent + 2);
|
||||||
|
for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
|
||||||
|
AstNode *child_node = node->data.switch_expr.prongs.at(i);
|
||||||
|
ast_print(child_node, indent + 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||||
|
for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
|
||||||
|
AstNode *child_node = node->data.switch_prong.items.at(i);
|
||||||
|
ast_print(child_node, indent + 2);
|
||||||
|
}
|
||||||
|
if (node->data.switch_prong.var_symbol) {
|
||||||
|
ast_print(node->data.switch_prong.var_symbol, indent + 2);
|
||||||
|
}
|
||||||
|
ast_print(node->data.switch_prong.expr, indent + 2);
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
|
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||||
|
ast_print(node->data.switch_range.start, indent + 2);
|
||||||
|
ast_print(node->data.switch_range.end, indent + 2);
|
||||||
|
break;
|
||||||
case NodeTypeLabel:
|
case NodeTypeLabel:
|
||||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
|
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
|
||||||
break;
|
break;
|
||||||
@ -2167,7 +2197,80 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BlockExpression : IfExpression | Block | WhileExpression | ForExpression
|
SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
|
||||||
|
SwitchProng : (list(SwitchItem, ",") | "else") option("," "(" "Symbol" ")") "=>" Expression ","
|
||||||
|
SwitchItem : Expression | (Expression "..." Expression)
|
||||||
|
*/
|
||||||
|
static AstNode *ast_parse_switch_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
|
|
||||||
|
if (token->id != TokenIdKeywordSwitch) {
|
||||||
|
if (mandatory) {
|
||||||
|
ast_invalid_token_error(pc, token);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*token_index += 1;
|
||||||
|
|
||||||
|
AstNode *node = ast_create_node(pc, NodeTypeSwitchExpr, token);
|
||||||
|
|
||||||
|
ast_eat_token(pc, token_index, TokenIdLParen);
|
||||||
|
node->data.switch_expr.expr = ast_parse_expression(pc, token_index, true);
|
||||||
|
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||||
|
ast_eat_token(pc, token_index, TokenIdLBrace);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
|
|
||||||
|
if (token->id == TokenIdRBrace) {
|
||||||
|
*token_index += 1;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *prong_node = ast_create_node(pc, NodeTypeSwitchProng, token);
|
||||||
|
node->data.switch_expr.prongs.append(prong_node);
|
||||||
|
|
||||||
|
if (token->id == TokenIdKeywordElse) {
|
||||||
|
*token_index += 1;
|
||||||
|
} else for (;;) {
|
||||||
|
AstNode *expr1 = ast_parse_expression(pc, token_index, true);
|
||||||
|
Token *ellipsis_tok = &pc->tokens->at(*token_index);
|
||||||
|
if (ellipsis_tok->id == TokenIdEllipsis) {
|
||||||
|
*token_index += 1;
|
||||||
|
|
||||||
|
AstNode *range_node = ast_create_node(pc, NodeTypeSwitchRange, ellipsis_tok);
|
||||||
|
prong_node->data.switch_prong.items.append(range_node);
|
||||||
|
|
||||||
|
range_node->data.switch_range.start = expr1;
|
||||||
|
range_node->data.switch_range.end = ast_parse_expression(pc, token_index, true);
|
||||||
|
} else {
|
||||||
|
prong_node->data.switch_prong.items.append(expr1);
|
||||||
|
}
|
||||||
|
Token *comma_tok = &pc->tokens->at(*token_index);
|
||||||
|
if (comma_tok->id == TokenIdComma) {
|
||||||
|
*token_index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token *arrow_or_comma = &pc->tokens->at(*token_index);
|
||||||
|
if (arrow_or_comma->id == TokenIdComma) {
|
||||||
|
*token_index += 1;
|
||||||
|
ast_eat_token(pc, token_index, TokenIdLParen);
|
||||||
|
prong_node->data.switch_prong.var_symbol = ast_parse_symbol(pc, token_index);
|
||||||
|
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_eat_token(pc, token_index, TokenIdFatArrow);
|
||||||
|
prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);
|
||||||
|
ast_eat_token(pc, token_index, TokenIdComma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
BlockExpression : IfExpression | Block | WhileExpression | ForExpression | SwitchExpression
|
||||||
*/
|
*/
|
||||||
static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
Token *token = &pc->tokens->at(*token_index);
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
@ -2176,10 +2279,6 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
|
|||||||
if (if_expr)
|
if (if_expr)
|
||||||
return if_expr;
|
return if_expr;
|
||||||
|
|
||||||
AstNode *block = ast_parse_block(pc, token_index, false);
|
|
||||||
if (block)
|
|
||||||
return block;
|
|
||||||
|
|
||||||
AstNode *while_expr = ast_parse_while_expr(pc, token_index, false);
|
AstNode *while_expr = ast_parse_while_expr(pc, token_index, false);
|
||||||
if (while_expr)
|
if (while_expr)
|
||||||
return while_expr;
|
return while_expr;
|
||||||
@ -2188,6 +2287,14 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
|
|||||||
if (for_expr)
|
if (for_expr)
|
||||||
return for_expr;
|
return for_expr;
|
||||||
|
|
||||||
|
AstNode *switch_expr = ast_parse_switch_expr(pc, token_index, false);
|
||||||
|
if (switch_expr)
|
||||||
|
return switch_expr;
|
||||||
|
|
||||||
|
AstNode *block = ast_parse_block(pc, token_index, false);
|
||||||
|
if (block)
|
||||||
|
return block;
|
||||||
|
|
||||||
if (mandatory)
|
if (mandatory)
|
||||||
ast_invalid_token_error(pc, token);
|
ast_invalid_token_error(pc, token);
|
||||||
|
|
||||||
|
@ -243,6 +243,8 @@ static void end_token(Tokenize *t) {
|
|||||||
t->cur_tok->id = TokenIdKeywordNull;
|
t->cur_tok->id = TokenIdKeywordNull;
|
||||||
} else if (mem_eql_str(token_mem, token_len, "noalias")) {
|
} else if (mem_eql_str(token_mem, token_len, "noalias")) {
|
||||||
t->cur_tok->id = TokenIdKeywordNoAlias;
|
t->cur_tok->id = TokenIdKeywordNoAlias;
|
||||||
|
} else if (mem_eql_str(token_mem, token_len, "switch")) {
|
||||||
|
t->cur_tok->id = TokenIdKeywordSwitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->cur_tok = nullptr;
|
t->cur_tok = nullptr;
|
||||||
@ -1035,6 +1037,7 @@ const char * token_name(TokenId id) {
|
|||||||
case TokenIdKeywordBreak: return "break";
|
case TokenIdKeywordBreak: return "break";
|
||||||
case TokenIdKeywordNull: return "null";
|
case TokenIdKeywordNull: return "null";
|
||||||
case TokenIdKeywordNoAlias: return "noalias";
|
case TokenIdKeywordNoAlias: return "noalias";
|
||||||
|
case TokenIdKeywordSwitch: return "switch";
|
||||||
case TokenIdLParen: return "(";
|
case TokenIdLParen: return "(";
|
||||||
case TokenIdRParen: return ")";
|
case TokenIdRParen: return ")";
|
||||||
case TokenIdComma: return ",";
|
case TokenIdComma: return ",";
|
||||||
|
@ -36,6 +36,7 @@ enum TokenId {
|
|||||||
TokenIdKeywordBreak,
|
TokenIdKeywordBreak,
|
||||||
TokenIdKeywordNull,
|
TokenIdKeywordNull,
|
||||||
TokenIdKeywordNoAlias,
|
TokenIdKeywordNoAlias,
|
||||||
|
TokenIdKeywordSwitch,
|
||||||
TokenIdLParen,
|
TokenIdLParen,
|
||||||
TokenIdRParen,
|
TokenIdRParen,
|
||||||
TokenIdComma,
|
TokenIdComma,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user