/* Bison parser for Rust expressions, for GDB.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
This file is part of GDB.
static const struct rust_op *ast_struct (const struct rust_op *name,
rust_set_vector *fields);
static const struct rust_op *ast_range (const struct rust_op *lhs,
- const struct rust_op *rhs);
+ const struct rust_op *rhs,
+ bool inclusive);
static const struct rust_op *ast_array_type (const struct rust_op *lhs,
struct typed_val_int val);
static const struct rust_op *ast_slice_type (const struct rust_op *type);
name occurred at the end of the expression and is eligible for
completion. */
unsigned int completing : 1;
+ /* For OP_RANGE, indicates whether the range is inclusive or
+ exclusive. */
+ unsigned int inclusive : 1;
/* Operands of expression. Which one is used and how depends on the
particular opcode. */
RUSTSTYPE left;
/* Operator tokens. */
%token <voidval> DOTDOT
+%token <voidval> DOTDOTEQ
%token <voidval> OROR
%token <voidval> ANDAND
%token <voidval> EQEQ
%type <one_field_init> struct_expr_tail
/* Precedence. */
-%nonassoc DOTDOT
+%nonassoc DOTDOT DOTDOTEQ
%right '=' COMPOUND_ASSIGN
%left OROR
%left ANDAND
| array_expr
| idx_expr
| range_expr
-| unop_expr /* Must precede call_expr because of ambiguity with sizeof. */
+| unop_expr /* Must precede call_expr because of ambiguity with
+ sizeof. */
| binop_expr
| paren_expr
| call_expr
struct typed_val_int val;
val.type
- = language_lookup_primitive_type (current_parser->language (),
- current_parser->arch (),
- "()");
+ = (language_lookup_primitive_type
+ (current_parser->language (), current_parser->arch (),
+ "()"));
val.val = 0;
$$ = ast_literal (val);
}
sf.init = $3;
$$ = sf;
}
+| IDENT
+ {
+ struct set_field sf;
+
+ sf.name = $1;
+ sf.init = ast_path ($1, NULL);
+ $$ = sf;
+ }
;
struct_expr_list:
$5->push_back (sf);
$$ = $5;
}
+| IDENT ',' struct_expr_list
+ {
+ struct set_field sf;
+
+ sf.name = $1;
+ sf.init = ast_path ($1, NULL);
+ $3->push_back (sf);
+ $$ = $3;
+ }
;
array_expr:
range_expr:
expr DOTDOT
- { $$ = ast_range ($1, NULL); }
+ { $$ = ast_range ($1, NULL, false); }
| expr DOTDOT expr
- { $$ = ast_range ($1, $3); }
+ { $$ = ast_range ($1, $3, false); }
+| expr DOTDOTEQ expr
+ { $$ = ast_range ($1, $3, true); }
| DOTDOT expr
- { $$ = ast_range (NULL, $2); }
+ { $$ = ast_range (NULL, $2, false); }
+| DOTDOTEQ expr
+ { $$ = ast_range (NULL, $2, true); }
| DOTDOT
- { $$ = ast_range (NULL, NULL); }
+ { $$ = ast_range (NULL, NULL, false); }
;
literal:
| '&' KW_MUT expr %prec UNARY
{ $$ = ast_unary (UNOP_ADDR, $3); }
-| KW_SIZEOF '(' expr ')' %prec UNARY
- { $$ = ast_unary (UNOP_SIZEOF, $3); }
+| KW_SIZEOF '(' expr ')' %prec UNARY
+ { $$ = ast_unary (UNOP_SIZEOF, $3); }
;
binop_expr:
;
paren_expr_list:
- '('
- maybe_expr_list
- ')'
+ '(' maybe_expr_list ')'
{ $$ = $2; }
;
just_identifiers_for_type:
IDENT
- { $$ = ast_path ($1, NULL); }
+ { $$ = ast_path ($1, NULL); }
| just_identifiers_for_type COLONCOLON IDENT
{
$$ = ast_path (rust_concat3 ($1->left.sval.ptr, "::",
{ "&=", COMPOUND_ASSIGN, BINOP_BITWISE_AND },
{ "|=", COMPOUND_ASSIGN, BINOP_BITWISE_IOR },
{ "^=", COMPOUND_ASSIGN, BINOP_BITWISE_XOR },
+ { "..=", DOTDOTEQ, OP_NULL },
{ "::", COLONCOLON, OP_NULL },
{ "..", DOTDOT, OP_NULL },
if (n_supers > 0)
{
- int i;
int len;
std::vector<int> offsets;
unsigned int current_len;
ident->right.params);
}
-/* A helper that updates innermost_block as appropriate. */
+/* A helper that updates the innermost block as appropriate. */
static void
update_innermost_block (struct block_symbol sym)
{
- if (symbol_read_needs_frame (sym.symbol)
- && (innermost_block == NULL
- || contained_in (sym.block, innermost_block)))
- innermost_block = sym.block;
+ if (symbol_read_needs_frame (sym.symbol))
+ innermost_block.update (sym);
}
/* A helper to look up a Rust type, or fail. This only works for
{
int is_byte = lexptr[0] == 'b';
int raw_length;
- int len_in_chars = 0;
if (is_byte)
++lexptr;
/* Make a range operation. */
static const struct rust_op *
-ast_range (const struct rust_op *lhs, const struct rust_op *rhs)
+ast_range (const struct rust_op *lhs, const struct rust_op *rhs,
+ bool inclusive)
{
struct rust_op *result = OBSTACK_ZALLOC (work_obstack, struct rust_op);
result->opcode = OP_RANGE;
+ result->inclusive = inclusive;
result->left.op = lhs;
result->right.op = rhs;
{
std::vector<struct type *> result;
- for (const rust_op *op : *params)
- result.push_back (convert_ast_to_type (state, op));
+ if (params != nullptr)
+ {
+ for (const rust_op *op : *params)
+ result.push_back (convert_ast_to_type (state, op));
+ }
return result;
}
std::vector<struct type *> args
(convert_params_to_types (state, operation->left.params));
int i;
- struct type *type;
const char *name;
obstack_1grow (work_obstack, '(');
case OP_AGGREGATE:
{
- int i;
int length;
rust_set_vector *fields = operation->right.field_inits;
struct type *type;
{
convert_ast_to_expression (state, operation->right.op, top);
if (kind == BOTH_BOUND_DEFAULT)
- kind = LOW_BOUND_DEFAULT;
+ kind = (operation->inclusive
+ ? LOW_BOUND_DEFAULT : LOW_BOUND_DEFAULT_EXCLUSIVE);
else
{
gdb_assert (kind == HIGH_BOUND_DEFAULT);
- kind = NONE_BOUND_DEFAULT;
+ kind = (operation->inclusive
+ ? NONE_BOUND_DEFAULT : NONE_BOUND_DEFAULT_EXCLUSIVE);
}
}
+ else
+ {
+ /* Nothing should make an inclusive range without an upper
+ bound. */
+ gdb_assert (!operation->inclusive);
+ }
+
write_exp_elt_opcode (state, OP_RANGE);
write_exp_elt_longcst (state, kind);
write_exp_elt_opcode (state, OP_RANGE);
&test_obstack);
// Set up dummy "parser", so that rust_type works.
- struct parser_state ps;
- initialize_expout (&ps, 0, &rust_language_defn, target_gdbarch ());
+ struct parser_state ps (0, &rust_language_defn, target_gdbarch ());
rust_parser parser (&ps);
rust_lex_test_one ("", 0);