aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp116
1 files changed, 74 insertions, 42 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 12293bc61b..6ce9e25221 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -221,6 +221,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory);
static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory);
static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index);
+static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index);
static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
if (token->id == token_id) {
@@ -240,7 +241,28 @@ static Token *ast_eat_token(ParseContext *pc, size_t *token_index, TokenId token
}
/*
-TypeExpr = PrefixOpExpression | "var"
+ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression
+*/
+static AstNode *ast_parse_error_set_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
+ AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory);
+ if (!prefix_op_expr) {
+ return nullptr;
+ }
+ Token *token = &pc->tokens->at(*token_index);
+ if (token->id == TokenIdBang) {
+ *token_index += 1;
+ AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
+ node->data.bin_op_expr.op1 = prefix_op_expr;
+ node->data.bin_op_expr.bin_op = BinOpTypeErrorUnion;
+ node->data.bin_op_expr.op2 = ast_parse_prefix_op_expr(pc, token_index, true);
+ return node;
+ } else {
+ return prefix_op_expr;
+ }
+}
+
+/*
+TypeExpr = ErrorSetExpr | "var"
*/
static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@@ -249,7 +271,7 @@ static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool
*token_index += 1;
return node;
} else {
- return ast_parse_prefix_op_expr(pc, token_index, mandatory);
+ return ast_parse_error_set_expr(pc, token_index, mandatory);
}
}
@@ -651,8 +673,9 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
}
/*
-PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | ("continue" option(":" Symbol))
+PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable"
+ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
*/
static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@@ -716,9 +739,31 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordError) {
- AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
- *token_index += 1;
- return node;
+ Token *next_token = &pc->tokens->at(*token_index + 1);
+ if (next_token->id == TokenIdLBrace) {
+ AstNode *node = ast_create_node(pc, NodeTypeErrorSetDecl, token);
+ *token_index += 2;
+ for (;;) {
+ Token *item_tok = &pc->tokens->at(*token_index);
+ if (item_tok->id == TokenIdRBrace) {
+ *token_index += 1;
+ return node;
+ } else if (item_tok->id == TokenIdSymbol) {
+ AstNode *symbol_node = ast_parse_symbol(pc, token_index);
+ node->data.err_set_decl.decls.append(symbol_node);
+ Token *opt_comma_tok = &pc->tokens->at(*token_index);
+ if (opt_comma_tok->id == TokenIdComma) {
+ *token_index += 1;
+ }
+ } else {
+ ast_invalid_token_error(pc, item_tok);
+ }
+ }
+ } else {
+ AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
+ *token_index += 1;
+ return node;
+ }
} else if (token->id == TokenIdAtSign) {
*token_index += 1;
Token *name_tok = &pc->tokens->at(*token_index);
@@ -950,7 +995,6 @@ static PrefixOp tok_to_prefix_op(Token *token) {
case TokenIdTilde: return PrefixOpBinNot;
case TokenIdStar: return PrefixOpDereference;
case TokenIdMaybe: return PrefixOpMaybe;
- case TokenIdPercent: return PrefixOpError;
case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
case TokenIdStarStar: return PrefixOpDereference;
default: return PrefixOpInvalid;
@@ -997,8 +1041,8 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
}
/*
-PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
-PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" | "try"
+PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression
+PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try"
*/
static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@@ -1028,7 +1072,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
node->column += 1;
}
- AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true);
+ AstNode *prefix_op_expr = ast_parse_error_set_expr(pc, token_index, true);
node->data.prefix_op_expr.primary_expr = prefix_op_expr;
node->data.prefix_op_expr.prefix_op = prefix_op;
@@ -1043,12 +1087,14 @@ static BinOpType tok_to_mult_op(Token *token) {
case TokenIdStarStar: return BinOpTypeArrayMult;
case TokenIdSlash: return BinOpTypeDiv;
case TokenIdPercent: return BinOpTypeMod;
+ case TokenIdBang: return BinOpTypeErrorUnion;
+ case TokenIdBarBar: return BinOpTypeMergeErrorSets;
default: return BinOpTypeInvalid;
}
}
/*
-MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
+MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
*/
static BinOpType ast_parse_mult_op(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@@ -2240,7 +2286,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
}
/*
-FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr
+FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
*/
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
Token *first_token = &pc->tokens->at(*token_index);
@@ -2315,6 +2361,18 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
ast_eat_token(pc, token_index, TokenIdRParen);
next_token = &pc->tokens->at(*token_index);
}
+ if (next_token->id == TokenIdKeywordError) {
+ Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1);
+ if (maybe_lbrace_tok->id == TokenIdLBrace) {
+ *token_index += 1;
+ node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token);
+ return node;
+ }
+ } else if (next_token->id == TokenIdBang) {
+ *token_index += 1;
+ node->data.fn_proto.auto_err_set = true;
+ next_token = &pc->tokens->at(*token_index);
+ }
node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true);
return node;
@@ -2531,7 +2589,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
Token *colon_token = &pc->tokens->at(*token_index);
if (colon_token->id == TokenIdColon) {
*token_index += 1;
- field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true);
+ field_node->data.struct_field.type = ast_parse_type_expr(pc, token_index, true);
}
Token *eq_token = &pc->tokens->at(*token_index);
if (eq_token->id == TokenIdEq) {
@@ -2560,26 +2618,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
}
/*
-ErrorValueDecl : "error" "Symbol" ";"
-*/
-static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index) {
- Token *first_token = &pc->tokens->at(*token_index);
-
- if (first_token->id != TokenIdKeywordError) {
- return nullptr;
- }
- *token_index += 1;
-
- Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
- ast_eat_token(pc, token_index, TokenIdSemicolon);
-
- AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
- node->data.error_value_decl.name = token_buf(name_tok);
-
- return node;
-}
-
-/*
TestDecl = "test" String Block
*/
static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index) {
@@ -2611,12 +2649,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
continue;
}
- AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index);
- if (error_value_node) {
- top_level_decls->append(error_value_node);
- continue;
- }
-
AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index);
if (test_decl_node) {
top_level_decls->append(test_decl_node);
@@ -2744,9 +2776,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.variable_declaration.align_expr, visit, context);
visit_field(&node->data.variable_declaration.section_expr, visit, context);
break;
- case NodeTypeErrorValueDecl:
- // none
- break;
case NodeTypeTestDecl:
visit_field(&node->data.test_decl.body, visit, context);
break;
@@ -2899,5 +2928,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.addr_of_expr.align_expr, visit, context);
visit_field(&node->data.addr_of_expr.op_expr, visit, context);
break;
+ case NodeTypeErrorSetDecl:
+ visit_node_list(&node->data.err_set_decl.decls, visit, context);
+ break;
}
}