From 6db6609df84bedafebc709bc5865e7f18c862cc6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 25 Jan 2016 13:53:40 -0700 Subject: implement %% operator See #23 --- src/parser.cpp | 78 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 23 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 523ad1a891..425651a4a2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -95,6 +95,8 @@ const char *node_type_str(NodeType node_type) { return "Block"; case NodeTypeBinOpExpr: return "BinOpExpr"; + case NodeTypeUnwrapErrorExpr: + return "UnwrapErrorExpr"; case NodeTypeFnCallExpr: return "FnCallExpr"; case NodeTypeArrayAccessExpr: @@ -273,6 +275,14 @@ void ast_print(AstNode *node, int indent) { ast_print(node->data.bin_op_expr.op1, indent + 2); ast_print(node->data.bin_op_expr.op2, indent + 2); break; + case NodeTypeUnwrapErrorExpr: + fprintf(stderr, "%s\n", node_type_str(node->type)); + ast_print(node->data.unwrap_err_expr.op1, indent + 2); + if (node->data.unwrap_err_expr.symbol) { + ast_print(node->data.unwrap_err_expr.symbol, indent + 2); + } + ast_print(node->data.unwrap_err_expr.op2, indent + 2); + break; case NodeTypeFnCallExpr: fprintf(stderr, "%s\n", node_type_str(node->type)); ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2); @@ -964,7 +974,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory); static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory); static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory); -static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory); +static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool mandatory); static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory); static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { @@ -1032,7 +1042,7 @@ static void ast_parse_directives(ParseContext *pc, int *token_index, } /* -ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis) +ParamDecl : option("noalias") "Symbol" ":" PrefixOpExpression | "..." */ static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) { Token *first_token = &pc->tokens->at(*token_index); @@ -1154,7 +1164,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool } /* -ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) UnwrapMaybeExpression +ArrayType : "[" option(Expression) "]" option("const") PrefixOpExpression */ static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *l_bracket = &pc->tokens->at(*token_index); @@ -1207,7 +1217,7 @@ static void ast_parse_asm_input_item(ParseContext *pc, int *token_index, AstNode } /* -AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) UnwrapMaybeExpression token(RParen) +AsmOutputItem : "[" "Symbol" "]" "String" "(" ("Symbol" | "->" PrefixOpExpression) ")" */ static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNode *node) { ast_eat_token(pc, token_index, TokenIdLBracket); @@ -2132,7 +2142,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m } /* -VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) UnwrapMaybeExpression option(token(Eq) Expression)) +VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression)) */ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *first_token = &pc->tokens->at(*token_index); @@ -2454,38 +2464,55 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool manda } /* -UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression +UnwrapExpression : BoolOrExpression (UnwrapMaybe | UnwrapError) | BoolOrExpression +UnwrapMaybe : "??" BoolOrExpression +UnwrapError : "%%" option("|" "Symbol" "|") BoolOrExpression */ -// this is currently the first child expression of assignment -static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory); if (!lhs) return nullptr; Token *token = &pc->tokens->at(*token_index); - if (token->id != TokenIdDoubleQuestion) { - return lhs; - } + if (token->id == TokenIdDoubleQuestion) { + *token_index += 1; - *token_index += 1; + AstNode *rhs = ast_parse_bool_or_expr(pc, token_index, true); - AstNode *rhs = ast_parse_bool_or_expr(pc, token_index, true); + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = lhs; + node->data.bin_op_expr.bin_op = BinOpTypeUnwrapMaybe; + node->data.bin_op_expr.op2 = rhs; - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = lhs; - node->data.bin_op_expr.bin_op = BinOpTypeUnwrapMaybe; - node->data.bin_op_expr.op2 = rhs; + normalize_parent_ptrs(node); + return node; + } else if (token->id == TokenIdPercentPercent) { + *token_index += 1; - normalize_parent_ptrs(node); - return node; + AstNode *node = ast_create_node(pc, NodeTypeUnwrapErrorExpr, token); + node->data.unwrap_err_expr.op1 = lhs; + + Token *maybe_bar_tok = &pc->tokens->at(*token_index); + if (maybe_bar_tok->id == TokenIdBinOr) { + *token_index += 1; + node->data.unwrap_err_expr.symbol = ast_parse_symbol(pc, token_index); + ast_eat_token(pc, token_index, TokenIdBinOr); + } + node->data.unwrap_err_expr.op2 = ast_parse_expression(pc, token_index, true); + + normalize_parent_ptrs(node); + return node; + } else { + return lhs; + } } /* -AssignmentExpression : UnwrapMaybeExpression AssignmentOperator UnwrapMaybeExpression | UnwrapMaybeExpression +AssignmentExpression : UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression */ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mandatory) { - AstNode *lhs = ast_parse_unwrap_maybe_expr(pc, token_index, mandatory); + AstNode *lhs = ast_parse_unwrap_expr(pc, token_index, mandatory); if (!lhs) return nullptr; @@ -2494,7 +2521,7 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand if (ass_op == BinOpTypeInvalid) return lhs; - AstNode *rhs = ast_parse_unwrap_maybe_expr(pc, token_index, true); + AstNode *rhs = ast_parse_unwrap_expr(pc, token_index, true); AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); node->data.bin_op_expr.op1 = lhs; @@ -2646,7 +2673,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato } /* -FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(UnwrapMaybeExpression) +FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option(PrefixOpExpression) */ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) { Token *first_token = &pc->tokens->at(*token_index); @@ -3164,6 +3191,11 @@ void normalize_parent_ptrs(AstNode *node) { set_field(&node->data.bin_op_expr.op1); set_field(&node->data.bin_op_expr.op2); break; + case NodeTypeUnwrapErrorExpr: + set_field(&node->data.unwrap_err_expr.op1); + set_field(&node->data.unwrap_err_expr.symbol); + set_field(&node->data.unwrap_err_expr.op2); + break; case NodeTypeNumberLiteral: // none break; -- cgit v1.2.3