mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
reduce precedence of {} suffix operator
this makes []u8 {1, 2, 3, 4} work for array literal
This commit is contained in:
parent
74b1665586
commit
0311b35a21
@ -34,7 +34,7 @@ Root : many(TopLevelDecl) token(EOF)
|
||||
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | ContainerDecl | VariableDeclaration
|
||||
|
||||
VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) UnwrapMaybeExpression option(token(Eq) Expression))
|
||||
VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) PrefixOpExpression option(token(Eq) Expression))
|
||||
|
||||
ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
|
||||
|
||||
@ -48,7 +48,7 @@ RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token
|
||||
|
||||
ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnDecl) token(RBrace)
|
||||
|
||||
FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(UnwrapMaybeExpression)
|
||||
FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(PrefixOpExpression)
|
||||
|
||||
Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)
|
||||
|
||||
@ -60,7 +60,7 @@ FnDef : FnProto token(FatArrow) Block
|
||||
|
||||
ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen)
|
||||
|
||||
ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis)
|
||||
ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) PrefixOpExpression | token(Ellipsis)
|
||||
|
||||
Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
|
||||
|
||||
@ -78,7 +78,7 @@ AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput)
|
||||
|
||||
AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers)
|
||||
|
||||
AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) UnwrapMaybeExpression) token(RParen)
|
||||
AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) PrefixOpExpression) token(RParen)
|
||||
|
||||
AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)
|
||||
|
||||
@ -102,7 +102,7 @@ IfExpression : IfVarExpression | IfBoolExpression
|
||||
|
||||
IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)
|
||||
|
||||
IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) UnwrapMaybeExpression) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)
|
||||
IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) PrefixOpExpression) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)
|
||||
|
||||
Else : token(Else) Expression
|
||||
|
||||
@ -126,13 +126,15 @@ AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | Mu
|
||||
|
||||
AdditionOperator : token(Plus) | token(Minus)
|
||||
|
||||
MultiplyExpression : PrefixOpExpression MultiplyOperator MultiplyExpression | PrefixOpExpression
|
||||
MultiplyExpression : CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
|
||||
|
||||
CurlySuffixExpression : PrefixOpExpression option(ContainerInitExpression)
|
||||
|
||||
MultiplyOperator : token(Star) | token(Slash) | token(Percent)
|
||||
|
||||
PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
|
||||
|
||||
SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
|
||||
SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
|
||||
|
||||
FieldAccessExpression : token(Dot) token(Symbol)
|
||||
|
||||
@ -152,7 +154,7 @@ PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampers
|
||||
|
||||
PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | token(Symbol) | (token(AtSign) token(Symbol) FnCallExpression) | ArrayType | AsmExpression
|
||||
|
||||
ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) UnwrapMaybeExpression
|
||||
ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) PrefixOpExpression
|
||||
|
||||
GotoExpression: token(Goto) token(Symbol)
|
||||
|
||||
@ -164,9 +166,9 @@ KeywordLiteral : token(True) | token(False) | token(Null) | token(Break) | token
|
||||
## Operator Precedence
|
||||
|
||||
```
|
||||
x() x[] x{} x.y
|
||||
!x -x ~x *x &x
|
||||
as
|
||||
x() x[] x.y
|
||||
!x -x ~x *x &x ?x
|
||||
x{}
|
||||
* / %
|
||||
+ -
|
||||
<< >>
|
||||
|
172
src/parser.cpp
172
src/parser.cpp
@ -903,6 +903,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
|
||||
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_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory);
|
||||
|
||||
static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
|
||||
if (token->id == token_id) {
|
||||
@ -998,7 +999,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {
|
||||
*token_index += 1;
|
||||
ast_expect_token(pc, colon, TokenIdColon);
|
||||
|
||||
node->data.param_decl.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
|
||||
node->data.param_decl.type = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -1114,7 +1115,7 @@ static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bo
|
||||
node->data.array_type.is_const = true;
|
||||
}
|
||||
|
||||
node->data.array_type.child_type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
|
||||
node->data.array_type.child_type = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -1159,7 +1160,7 @@ static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNod
|
||||
if (token->id == TokenIdSymbol) {
|
||||
ast_buf_from_token(pc, token, &asm_output->variable_name);
|
||||
} else if (token->id == TokenIdArrow) {
|
||||
asm_output->return_type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
|
||||
asm_output->return_type = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
} else {
|
||||
ast_invalid_token_error(pc, token);
|
||||
}
|
||||
@ -1402,13 +1403,95 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
|
||||
}
|
||||
|
||||
/*
|
||||
SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
|
||||
CurlySuffixExpression : PrefixOpExpression option(ContainerInitExpression)
|
||||
ContainerInitExpression : token(LBrace) ContainerInitBody token(RBrace)
|
||||
ContainerInitBody : list(StructLiteralField, token(Comma)) | list(Expression, token(Comma))
|
||||
*/
|
||||
static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory);
|
||||
if (!prefix_op_expr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
if (first_token->id == TokenIdLBrace) {
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, first_token);
|
||||
node->data.container_init_expr.type = prefix_op_expr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdDot) {
|
||||
for (;;) {
|
||||
if (token->id == TokenIdDot) {
|
||||
ast_eat_token(pc, token_index, TokenIdDot);
|
||||
Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
ast_eat_token(pc, token_index, TokenIdEq);
|
||||
|
||||
AstNode *field_node = ast_create_node(pc, NodeTypeStructValueField, token);
|
||||
|
||||
ast_buf_from_token(pc, field_name_tok, &field_node->data.struct_val_field.name);
|
||||
field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true);
|
||||
|
||||
node->data.container_init_expr.entries.append(field_node);
|
||||
|
||||
Token *comma_tok = &pc->tokens->at(*token_index);
|
||||
if (comma_tok->id == TokenIdComma) {
|
||||
*token_index += 1;
|
||||
token = &pc->tokens->at(*token_index);
|
||||
continue;
|
||||
} else if (comma_tok->id != TokenIdRBrace) {
|
||||
ast_invalid_token_error(pc, comma_tok);
|
||||
} else {
|
||||
*token_index += 1;
|
||||
break;
|
||||
}
|
||||
} else if (token->id == TokenIdRBrace) {
|
||||
*token_index += 1;
|
||||
break;
|
||||
} else {
|
||||
ast_invalid_token_error(pc, token);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (;;) {
|
||||
if (token->id == TokenIdRBrace) {
|
||||
*token_index += 1;
|
||||
break;
|
||||
} else {
|
||||
AstNode *elem_node = ast_parse_expression(pc, token_index, true);
|
||||
node->data.container_init_expr.entries.append(elem_node);
|
||||
|
||||
Token *comma_tok = &pc->tokens->at(*token_index);
|
||||
if (comma_tok->id == TokenIdComma) {
|
||||
*token_index += 1;
|
||||
token = &pc->tokens->at(*token_index);
|
||||
continue;
|
||||
} else if (comma_tok->id != TokenIdRBrace) {
|
||||
ast_invalid_token_error(pc, comma_tok);
|
||||
} else {
|
||||
*token_index += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prefix_op_expr = node;
|
||||
} else {
|
||||
return prefix_op_expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
|
||||
FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
|
||||
ArrayAccessExpression : token(LBracket) Expression token(RBracket)
|
||||
SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
|
||||
FieldAccessExpression : token(Dot) token(Symbol)
|
||||
ContainerInitExpression : token(LBrace) ContainerInitBody token(RBrace)
|
||||
ContainerInitBody : list(StructLiteralField, token(Comma)) | list(Expression, token(Comma))
|
||||
StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
|
||||
*/
|
||||
static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
@ -1471,71 +1554,6 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
|
||||
node->data.field_access_expr.struct_expr = primary_expr;
|
||||
ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name);
|
||||
|
||||
primary_expr = node;
|
||||
} else if (first_token->id == TokenIdLBrace) {
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, first_token);
|
||||
node->data.container_init_expr.type = primary_expr;
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdDot) {
|
||||
for (;;) {
|
||||
if (token->id == TokenIdDot) {
|
||||
ast_eat_token(pc, token_index, TokenIdDot);
|
||||
Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
ast_eat_token(pc, token_index, TokenIdEq);
|
||||
|
||||
AstNode *field_node = ast_create_node(pc, NodeTypeStructValueField, token);
|
||||
|
||||
ast_buf_from_token(pc, field_name_tok, &field_node->data.struct_val_field.name);
|
||||
field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true);
|
||||
|
||||
node->data.container_init_expr.entries.append(field_node);
|
||||
|
||||
Token *comma_tok = &pc->tokens->at(*token_index);
|
||||
if (comma_tok->id == TokenIdComma) {
|
||||
*token_index += 1;
|
||||
token = &pc->tokens->at(*token_index);
|
||||
continue;
|
||||
} else if (comma_tok->id != TokenIdRBrace) {
|
||||
ast_invalid_token_error(pc, comma_tok);
|
||||
} else {
|
||||
*token_index += 1;
|
||||
break;
|
||||
}
|
||||
} else if (token->id == TokenIdRBrace) {
|
||||
*token_index += 1;
|
||||
break;
|
||||
} else {
|
||||
ast_invalid_token_error(pc, token);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (;;) {
|
||||
if (token->id == TokenIdRBrace) {
|
||||
*token_index += 1;
|
||||
break;
|
||||
} else {
|
||||
AstNode *elem_node = ast_parse_expression(pc, token_index, true);
|
||||
node->data.container_init_expr.entries.append(elem_node);
|
||||
|
||||
Token *comma_tok = &pc->tokens->at(*token_index);
|
||||
if (comma_tok->id == TokenIdComma) {
|
||||
*token_index += 1;
|
||||
token = &pc->tokens->at(*token_index);
|
||||
continue;
|
||||
} else if (comma_tok->id != TokenIdRBrace) {
|
||||
ast_invalid_token_error(pc, comma_tok);
|
||||
} else {
|
||||
*token_index += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
primary_expr = node;
|
||||
} else {
|
||||
return primary_expr;
|
||||
@ -1623,10 +1641,10 @@ static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mand
|
||||
}
|
||||
|
||||
/*
|
||||
MultiplyExpression : PrefixOpExpression MultiplyOperator MultiplyExpression | PrefixOpExpression
|
||||
MultiplyExpression : CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
|
||||
*/
|
||||
static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory);
|
||||
AstNode *operand_1 = ast_parse_curly_suffix_expr(pc, token_index, mandatory);
|
||||
if (!operand_1)
|
||||
return nullptr;
|
||||
|
||||
@ -1636,7 +1654,7 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man
|
||||
if (mult_op == BinOpTypeInvalid)
|
||||
return operand_1;
|
||||
|
||||
AstNode *operand_2 = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
AstNode *operand_2 = ast_parse_curly_suffix_expr(pc, token_index, true);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
|
||||
node->data.bin_op_expr.op1 = operand_1;
|
||||
@ -1948,7 +1966,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
|
||||
node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
|
||||
} else if (eq_or_colon->id == TokenIdColon) {
|
||||
*token_index += 1;
|
||||
node->data.if_var_expr.var_decl.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
|
||||
node->data.if_var_expr.var_decl.type = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdMaybeAssign);
|
||||
node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
|
||||
@ -2028,7 +2046,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
|
||||
node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
|
||||
return node;
|
||||
} else if (eq_or_colon->id == TokenIdColon) {
|
||||
node->data.variable_declaration.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
|
||||
node->data.variable_declaration.type = ast_parse_prefix_op_expr(pc, token_index, true);
|
||||
Token *eq_token = &pc->tokens->at(*token_index);
|
||||
if (eq_token->id == TokenIdEq) {
|
||||
*token_index += 1;
|
||||
@ -2394,7 +2412,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
|
||||
ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);
|
||||
|
||||
Token *next_token = &pc->tokens->at(*token_index);
|
||||
node->data.fn_proto.return_type = ast_parse_unwrap_maybe_expr(pc, token_index, false);
|
||||
node->data.fn_proto.return_type = ast_parse_prefix_op_expr(pc, token_index, false);
|
||||
if (!node->data.fn_proto.return_type) {
|
||||
node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user