/* 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.
struct typed_val_float
{
- DOUBLEST dval;
+ gdb_byte val[16];
struct type *type;
};
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);
static regex_t number_regex;
-/* True if we're running unit tests. */
-
-static int unit_testing;
-
/* Obstack for data temporarily allocated during parsing. Points to
the obstack in the rust_parser, or to a temporary obstack during
unit testing. */
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
{
struct type *type;
- /* When unit testing, we don't bother checking the types, so avoid a
- possibly-failing lookup here. */
- if (unit_testing)
- return NULL;
-
type = language_lookup_primitive_type (current_parser->language (),
current_parser->arch (),
name);
{
int is_byte = lexptr[0] == 'b';
int raw_length;
- int len_in_chars = 0;
if (is_byte)
++lexptr;
}
else
{
- rustyylval.typed_val_float.dval = strtod (number.c_str (), NULL);
rustyylval.typed_val_float.type = type;
+ bool parsed = parse_float (number.c_str (), number.length (),
+ rustyylval.typed_val_float.type,
+ rustyylval.typed_val_float.val);
+ gdb_assert (parsed);
}
return is_integer ? (could_be_decimal ? DECIMAL_INTEGER : INTEGER) : FLOAT;
{
struct rust_op *result = OBSTACK_ZALLOC (work_obstack, struct rust_op);
- result->opcode = OP_DOUBLE;
+ result->opcode = OP_FLOAT;
result->left.typed_val_float = val;
return result;
/* 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, '(');
write_exp_elt_opcode (state, OP_LONG);
break;
- case OP_DOUBLE:
- write_exp_elt_opcode (state, OP_DOUBLE);
+ case OP_FLOAT:
+ write_exp_elt_opcode (state, OP_FLOAT);
write_exp_elt_type (state, operation->left.typed_val_float.type);
- write_exp_elt_dblcst (state, operation->left.typed_val_float.dval);
- write_exp_elt_opcode (state, OP_DOUBLE);
+ write_exp_elt_floatcst (state, operation->left.typed_val_float.val);
+ write_exp_elt_opcode (state, OP_FLOAT);
break;
case STRUCTOP_STRUCT:
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);
scoped_restore obstack_holder = make_scoped_restore (&work_obstack,
&test_obstack);
- unit_testing = 1;
+ // Set up dummy "parser", so that rust_type works.
+ struct parser_state ps (0, &rust_language_defn, target_gdbarch ());
+ rust_parser parser (&ps);
rust_lex_test_one ("", 0);
rust_lex_test_one (" \t \n \r ", 0);
rust_lex_test_completion ();
rust_lex_test_push_back ();
-
- unit_testing = 0;
}
#endif /* GDB_SELF_TEST */
gdb_assert (code == 0);
#if GDB_SELF_TEST
- selftests::register_test (rust_lex_tests);
+ selftests::register_test ("rust-lex", rust_lex_tests);
#endif
}