rust-parse.c revision 1.1 1 1.1 christos /* Rust expression parsing for GDB, the GNU debugger.
2 1.1 christos
3 1.1 christos Copyright (C) 2016-2023 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos #include "defs.h"
21 1.1 christos
22 1.1 christos #include "block.h"
23 1.1 christos #include "charset.h"
24 1.1 christos #include "cp-support.h"
25 1.1 christos #include "gdbsupport/gdb_obstack.h"
26 1.1 christos #include "gdbsupport/gdb_regex.h"
27 1.1 christos #include "rust-lang.h"
28 1.1 christos #include "parser-defs.h"
29 1.1 christos #include "gdbsupport/selftest.h"
30 1.1 christos #include "value.h"
31 1.1 christos #include "gdbarch.h"
32 1.1 christos #include "rust-exp.h"
33 1.1 christos
34 1.1 christos using namespace expr;
35 1.1 christos
36 1.1 christos /* A regular expression for matching Rust numbers. This is split up
37 1.1 christos since it is very long and this gives us a way to comment the
38 1.1 christos sections. */
39 1.1 christos
40 1.1 christos static const char number_regex_text[] =
41 1.1 christos /* subexpression 1: allows use of alternation, otherwise uninteresting */
42 1.1 christos "^("
43 1.1 christos /* First comes floating point. */
44 1.1 christos /* Recognize number after the decimal point, with optional
45 1.1 christos exponent and optional type suffix.
46 1.1 christos subexpression 2: allows "?", otherwise uninteresting
47 1.1 christos subexpression 3: if present, type suffix
48 1.1 christos */
49 1.1 christos "[0-9][0-9_]*\\.[0-9][0-9_]*([eE][-+]?[0-9][0-9_]*)?(f32|f64)?"
50 1.1 christos #define FLOAT_TYPE1 3
51 1.1 christos "|"
52 1.1 christos /* Recognize exponent without decimal point, with optional type
53 1.1 christos suffix.
54 1.1 christos subexpression 4: if present, type suffix
55 1.1 christos */
56 1.1 christos #define FLOAT_TYPE2 4
57 1.1 christos "[0-9][0-9_]*[eE][-+]?[0-9][0-9_]*(f32|f64)?"
58 1.1 christos "|"
59 1.1 christos /* "23." is a valid floating point number, but "23.e5" and
60 1.1 christos "23.f32" are not. So, handle the trailing-. case
61 1.1 christos separately. */
62 1.1 christos "[0-9][0-9_]*\\."
63 1.1 christos "|"
64 1.1 christos /* Finally come integers.
65 1.1 christos subexpression 5: text of integer
66 1.1 christos subexpression 6: if present, type suffix
67 1.1 christos subexpression 7: allows use of alternation, otherwise uninteresting
68 1.1 christos */
69 1.1 christos #define INT_TEXT 5
70 1.1 christos #define INT_TYPE 6
71 1.1 christos "(0x[a-fA-F0-9_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*)"
72 1.1 christos "([iu](size|8|16|32|64))?"
73 1.1 christos ")";
74 1.1 christos /* The number of subexpressions to allocate space for, including the
75 1.1 christos "0th" whole match subexpression. */
76 1.1 christos #define NUM_SUBEXPRESSIONS 8
77 1.1 christos
78 1.1 christos /* The compiled number-matching regex. */
79 1.1 christos
80 1.1 christos static regex_t number_regex;
81 1.1 christos
82 1.1 christos /* The kinds of tokens. Note that single-character tokens are
83 1.1 christos represented by themselves, so for instance '[' is a token. */
84 1.1 christos enum token_type : int
85 1.1 christos {
86 1.1 christos /* Make sure to start after any ASCII character. */
87 1.1 christos GDBVAR = 256,
88 1.1 christos IDENT,
89 1.1 christos COMPLETE,
90 1.1 christos INTEGER,
91 1.1 christos DECIMAL_INTEGER,
92 1.1 christos STRING,
93 1.1 christos BYTESTRING,
94 1.1 christos FLOAT,
95 1.1 christos COMPOUND_ASSIGN,
96 1.1 christos
97 1.1 christos /* Keyword tokens. */
98 1.1 christos KW_AS,
99 1.1 christos KW_IF,
100 1.1 christos KW_TRUE,
101 1.1 christos KW_FALSE,
102 1.1 christos KW_SUPER,
103 1.1 christos KW_SELF,
104 1.1 christos KW_MUT,
105 1.1 christos KW_EXTERN,
106 1.1 christos KW_CONST,
107 1.1 christos KW_FN,
108 1.1 christos KW_SIZEOF,
109 1.1 christos
110 1.1 christos /* Operator tokens. */
111 1.1 christos DOTDOT,
112 1.1 christos DOTDOTEQ,
113 1.1 christos OROR,
114 1.1 christos ANDAND,
115 1.1 christos EQEQ,
116 1.1 christos NOTEQ,
117 1.1 christos LTEQ,
118 1.1 christos GTEQ,
119 1.1 christos LSH,
120 1.1 christos RSH,
121 1.1 christos COLONCOLON,
122 1.1 christos ARROW,
123 1.1 christos };
124 1.1 christos
125 1.1 christos /* A typed integer constant. */
126 1.1 christos
127 1.1 christos struct typed_val_int
128 1.1 christos {
129 1.1 christos ULONGEST val;
130 1.1 christos struct type *type;
131 1.1 christos };
132 1.1 christos
133 1.1 christos /* A typed floating point constant. */
134 1.1 christos
135 1.1 christos struct typed_val_float
136 1.1 christos {
137 1.1 christos float_data val;
138 1.1 christos struct type *type;
139 1.1 christos };
140 1.1 christos
141 1.1 christos /* A struct of this type is used to describe a token. */
142 1.1 christos
143 1.1 christos struct token_info
144 1.1 christos {
145 1.1 christos const char *name;
146 1.1 christos int value;
147 1.1 christos enum exp_opcode opcode;
148 1.1 christos };
149 1.1 christos
150 1.1 christos /* Identifier tokens. */
151 1.1 christos
152 1.1 christos static const struct token_info identifier_tokens[] =
153 1.1 christos {
154 1.1 christos { "as", KW_AS, OP_NULL },
155 1.1 christos { "false", KW_FALSE, OP_NULL },
156 1.1 christos { "if", 0, OP_NULL },
157 1.1 christos { "mut", KW_MUT, OP_NULL },
158 1.1 christos { "const", KW_CONST, OP_NULL },
159 1.1 christos { "self", KW_SELF, OP_NULL },
160 1.1 christos { "super", KW_SUPER, OP_NULL },
161 1.1 christos { "true", KW_TRUE, OP_NULL },
162 1.1 christos { "extern", KW_EXTERN, OP_NULL },
163 1.1 christos { "fn", KW_FN, OP_NULL },
164 1.1 christos { "sizeof", KW_SIZEOF, OP_NULL },
165 1.1 christos };
166 1.1 christos
167 1.1 christos /* Operator tokens, sorted longest first. */
168 1.1 christos
169 1.1 christos static const struct token_info operator_tokens[] =
170 1.1 christos {
171 1.1 christos { ">>=", COMPOUND_ASSIGN, BINOP_RSH },
172 1.1 christos { "<<=", COMPOUND_ASSIGN, BINOP_LSH },
173 1.1 christos
174 1.1 christos { "<<", LSH, OP_NULL },
175 1.1 christos { ">>", RSH, OP_NULL },
176 1.1 christos { "&&", ANDAND, OP_NULL },
177 1.1 christos { "||", OROR, OP_NULL },
178 1.1 christos { "==", EQEQ, OP_NULL },
179 1.1 christos { "!=", NOTEQ, OP_NULL },
180 1.1 christos { "<=", LTEQ, OP_NULL },
181 1.1 christos { ">=", GTEQ, OP_NULL },
182 1.1 christos { "+=", COMPOUND_ASSIGN, BINOP_ADD },
183 1.1 christos { "-=", COMPOUND_ASSIGN, BINOP_SUB },
184 1.1 christos { "*=", COMPOUND_ASSIGN, BINOP_MUL },
185 1.1 christos { "/=", COMPOUND_ASSIGN, BINOP_DIV },
186 1.1 christos { "%=", COMPOUND_ASSIGN, BINOP_REM },
187 1.1 christos { "&=", COMPOUND_ASSIGN, BINOP_BITWISE_AND },
188 1.1 christos { "|=", COMPOUND_ASSIGN, BINOP_BITWISE_IOR },
189 1.1 christos { "^=", COMPOUND_ASSIGN, BINOP_BITWISE_XOR },
190 1.1 christos { "..=", DOTDOTEQ, OP_NULL },
191 1.1 christos
192 1.1 christos { "::", COLONCOLON, OP_NULL },
193 1.1 christos { "..", DOTDOT, OP_NULL },
194 1.1 christos { "->", ARROW, OP_NULL }
195 1.1 christos };
196 1.1 christos
197 1.1 christos /* An instance of this is created before parsing, and destroyed when
198 1.1 christos parsing is finished. */
199 1.1 christos
200 1.1 christos struct rust_parser
201 1.1 christos {
202 1.1 christos explicit rust_parser (struct parser_state *state)
203 1.1 christos : pstate (state)
204 1.1 christos {
205 1.1 christos }
206 1.1 christos
207 1.1 christos DISABLE_COPY_AND_ASSIGN (rust_parser);
208 1.1 christos
209 1.1 christos /* Return the parser's language. */
210 1.1 christos const struct language_defn *language () const
211 1.1 christos {
212 1.1 christos return pstate->language ();
213 1.1 christos }
214 1.1 christos
215 1.1 christos /* Return the parser's gdbarch. */
216 1.1 christos struct gdbarch *arch () const
217 1.1 christos {
218 1.1 christos return pstate->gdbarch ();
219 1.1 christos }
220 1.1 christos
221 1.1 christos /* A helper to look up a Rust type, or fail. This only works for
222 1.1 christos types defined by rust_language_arch_info. */
223 1.1 christos
224 1.1 christos struct type *get_type (const char *name)
225 1.1 christos {
226 1.1 christos struct type *type;
227 1.1 christos
228 1.1 christos type = language_lookup_primitive_type (language (), arch (), name);
229 1.1 christos if (type == NULL)
230 1.1 christos error (_("Could not find Rust type %s"), name);
231 1.1 christos return type;
232 1.1 christos }
233 1.1 christos
234 1.1 christos std::string crate_name (const std::string &name);
235 1.1 christos std::string super_name (const std::string &ident, unsigned int n_supers);
236 1.1 christos
237 1.1 christos int lex_character ();
238 1.1 christos int lex_number ();
239 1.1 christos int lex_string ();
240 1.1 christos int lex_identifier ();
241 1.1 christos uint32_t lex_hex (int min, int max);
242 1.1 christos uint32_t lex_escape (int is_byte);
243 1.1 christos int lex_operator ();
244 1.1 christos int lex_one_token ();
245 1.1 christos void push_back (char c);
246 1.1 christos
247 1.1 christos /* The main interface to lexing. Lexes one token and updates the
248 1.1 christos internal state. */
249 1.1 christos void lex ()
250 1.1 christos {
251 1.1 christos current_token = lex_one_token ();
252 1.1 christos }
253 1.1 christos
254 1.1 christos /* Assuming the current token is TYPE, lex the next token. */
255 1.1 christos void assume (int type)
256 1.1 christos {
257 1.1 christos gdb_assert (current_token == type);
258 1.1 christos lex ();
259 1.1 christos }
260 1.1 christos
261 1.1 christos /* Require the single-character token C, and lex the next token; or
262 1.1 christos throw an exception. */
263 1.1 christos void require (char type)
264 1.1 christos {
265 1.1 christos if (current_token != type)
266 1.1 christos error (_("'%c' expected"), type);
267 1.1 christos lex ();
268 1.1 christos }
269 1.1 christos
270 1.1 christos /* Entry point for all parsing. */
271 1.1 christos operation_up parse_entry_point ()
272 1.1 christos {
273 1.1 christos lex ();
274 1.1 christos operation_up result = parse_expr ();
275 1.1 christos if (current_token != 0)
276 1.1 christos error (_("Syntax error near '%s'"), pstate->prev_lexptr);
277 1.1 christos return result;
278 1.1 christos }
279 1.1 christos
280 1.1 christos operation_up parse_tuple ();
281 1.1 christos operation_up parse_array ();
282 1.1 christos operation_up name_to_operation (const std::string &name);
283 1.1 christos operation_up parse_struct_expr (struct type *type);
284 1.1 christos operation_up parse_binop (bool required);
285 1.1 christos operation_up parse_range ();
286 1.1 christos operation_up parse_expr ();
287 1.1 christos operation_up parse_sizeof ();
288 1.1 christos operation_up parse_addr ();
289 1.1 christos operation_up parse_field (operation_up &&);
290 1.1 christos operation_up parse_index (operation_up &&);
291 1.1 christos std::vector<operation_up> parse_paren_args ();
292 1.1 christos operation_up parse_call (operation_up &&);
293 1.1 christos std::vector<struct type *> parse_type_list ();
294 1.1 christos std::vector<struct type *> parse_maybe_type_list ();
295 1.1 christos struct type *parse_array_type ();
296 1.1 christos struct type *parse_slice_type ();
297 1.1 christos struct type *parse_pointer_type ();
298 1.1 christos struct type *parse_function_type ();
299 1.1 christos struct type *parse_tuple_type ();
300 1.1 christos struct type *parse_type ();
301 1.1 christos std::string parse_path (bool for_expr);
302 1.1 christos operation_up parse_string ();
303 1.1 christos operation_up parse_tuple_struct (struct type *type);
304 1.1 christos operation_up parse_path_expr ();
305 1.1 christos operation_up parse_atom (bool required);
306 1.1 christos
307 1.1 christos void update_innermost_block (struct block_symbol sym);
308 1.1 christos struct block_symbol lookup_symbol (const char *name,
309 1.1 christos const struct block *block,
310 1.1 christos const domain_enum domain);
311 1.1 christos struct type *rust_lookup_type (const char *name);
312 1.1 christos
313 1.1 christos /* Clear some state. This is only used for testing. */
314 1.1 christos #if GDB_SELF_TEST
315 1.1 christos void reset (const char *input)
316 1.1 christos {
317 1.1 christos pstate->prev_lexptr = nullptr;
318 1.1 christos pstate->lexptr = input;
319 1.1 christos paren_depth = 0;
320 1.1 christos current_token = 0;
321 1.1 christos current_int_val = {};
322 1.1 christos current_float_val = {};
323 1.1 christos current_string_val = {};
324 1.1 christos current_opcode = OP_NULL;
325 1.1 christos }
326 1.1 christos #endif /* GDB_SELF_TEST */
327 1.1 christos
328 1.1 christos /* Return the token's string value as a string. */
329 1.1 christos std::string get_string () const
330 1.1 christos {
331 1.1 christos return std::string (current_string_val.ptr, current_string_val.length);
332 1.1 christos }
333 1.1 christos
334 1.1 christos /* A pointer to this is installed globally. */
335 1.1 christos auto_obstack obstack;
336 1.1 christos
337 1.1 christos /* The parser state gdb gave us. */
338 1.1 christos struct parser_state *pstate;
339 1.1 christos
340 1.1 christos /* Depth of parentheses. */
341 1.1 christos int paren_depth = 0;
342 1.1 christos
343 1.1 christos /* The current token's type. */
344 1.1 christos int current_token = 0;
345 1.1 christos /* The current token's payload, if any. */
346 1.1 christos typed_val_int current_int_val {};
347 1.1 christos typed_val_float current_float_val {};
348 1.1 christos struct stoken current_string_val {};
349 1.1 christos enum exp_opcode current_opcode = OP_NULL;
350 1.1 christos
351 1.1 christos /* When completing, this may be set to the field operation to
352 1.1 christos complete. */
353 1.1 christos operation_up completion_op;
354 1.1 christos };
355 1.1 christos
356 1.1 christos /* Return an string referring to NAME, but relative to the crate's
357 1.1 christos name. */
358 1.1 christos
359 1.1 christos std::string
360 1.1 christos rust_parser::crate_name (const std::string &name)
361 1.1 christos {
362 1.1 christos std::string crate = rust_crate_for_block (pstate->expression_context_block);
363 1.1 christos
364 1.1 christos if (crate.empty ())
365 1.1 christos error (_("Could not find crate for current location"));
366 1.1 christos return "::" + crate + "::" + name;
367 1.1 christos }
368 1.1 christos
369 1.1 christos /* Return a string referring to a "super::" qualified name. IDENT is
370 1.1 christos the base name and N_SUPERS is how many "super::"s were provided.
371 1.1 christos N_SUPERS can be zero. */
372 1.1 christos
373 1.1 christos std::string
374 1.1 christos rust_parser::super_name (const std::string &ident, unsigned int n_supers)
375 1.1 christos {
376 1.1 christos const char *scope = block_scope (pstate->expression_context_block);
377 1.1 christos int offset;
378 1.1 christos
379 1.1 christos if (scope[0] == '\0')
380 1.1 christos error (_("Couldn't find namespace scope for self::"));
381 1.1 christos
382 1.1 christos if (n_supers > 0)
383 1.1 christos {
384 1.1 christos int len;
385 1.1 christos std::vector<int> offsets;
386 1.1 christos unsigned int current_len;
387 1.1 christos
388 1.1 christos current_len = cp_find_first_component (scope);
389 1.1 christos while (scope[current_len] != '\0')
390 1.1 christos {
391 1.1 christos offsets.push_back (current_len);
392 1.1 christos gdb_assert (scope[current_len] == ':');
393 1.1 christos /* The "::". */
394 1.1 christos current_len += 2;
395 1.1 christos current_len += cp_find_first_component (scope
396 1.1 christos + current_len);
397 1.1 christos }
398 1.1 christos
399 1.1 christos len = offsets.size ();
400 1.1 christos if (n_supers >= len)
401 1.1 christos error (_("Too many super:: uses from '%s'"), scope);
402 1.1 christos
403 1.1 christos offset = offsets[len - n_supers];
404 1.1 christos }
405 1.1 christos else
406 1.1 christos offset = strlen (scope);
407 1.1 christos
408 1.1 christos return "::" + std::string (scope, offset) + "::" + ident;
409 1.1 christos }
410 1.1 christos
411 1.1 christos /* A helper to appropriately munge NAME and BLOCK depending on the
412 1.1 christos presence of a leading "::". */
413 1.1 christos
414 1.1 christos static void
415 1.1 christos munge_name_and_block (const char **name, const struct block **block)
416 1.1 christos {
417 1.1 christos /* If it is a global reference, skip the current block in favor of
418 1.1 christos the static block. */
419 1.1 christos if (startswith (*name, "::"))
420 1.1 christos {
421 1.1 christos *name += 2;
422 1.1 christos *block = block_static_block (*block);
423 1.1 christos }
424 1.1 christos }
425 1.1 christos
426 1.1 christos /* Like lookup_symbol, but handles Rust namespace conventions, and
427 1.1 christos doesn't require field_of_this_result. */
428 1.1 christos
429 1.1 christos struct block_symbol
430 1.1 christos rust_parser::lookup_symbol (const char *name, const struct block *block,
431 1.1 christos const domain_enum domain)
432 1.1 christos {
433 1.1 christos struct block_symbol result;
434 1.1 christos
435 1.1 christos munge_name_and_block (&name, &block);
436 1.1 christos
437 1.1 christos result = ::lookup_symbol (name, block, domain, NULL);
438 1.1 christos if (result.symbol != NULL)
439 1.1 christos update_innermost_block (result);
440 1.1 christos return result;
441 1.1 christos }
442 1.1 christos
443 1.1 christos /* Look up a type, following Rust namespace conventions. */
444 1.1 christos
445 1.1 christos struct type *
446 1.1 christos rust_parser::rust_lookup_type (const char *name)
447 1.1 christos {
448 1.1 christos struct block_symbol result;
449 1.1 christos struct type *type;
450 1.1 christos
451 1.1 christos const struct block *block = pstate->expression_context_block;
452 1.1 christos munge_name_and_block (&name, &block);
453 1.1 christos
454 1.1 christos result = ::lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
455 1.1 christos if (result.symbol != NULL)
456 1.1 christos {
457 1.1 christos update_innermost_block (result);
458 1.1 christos return result.symbol->type ();
459 1.1 christos }
460 1.1 christos
461 1.1 christos type = lookup_typename (language (), name, NULL, 1);
462 1.1 christos if (type != NULL)
463 1.1 christos return type;
464 1.1 christos
465 1.1 christos /* Last chance, try a built-in type. */
466 1.1 christos return language_lookup_primitive_type (language (), arch (), name);
467 1.1 christos }
468 1.1 christos
469 1.1 christos /* A helper that updates the innermost block as appropriate. */
470 1.1 christos
471 1.1 christos void
472 1.1 christos rust_parser::update_innermost_block (struct block_symbol sym)
473 1.1 christos {
474 1.1 christos if (symbol_read_needs_frame (sym.symbol))
475 1.1 christos pstate->block_tracker->update (sym);
476 1.1 christos }
477 1.1 christos
478 1.1 christos /* Lex a hex number with at least MIN digits and at most MAX
479 1.1 christos digits. */
480 1.1 christos
481 1.1 christos uint32_t
482 1.1 christos rust_parser::lex_hex (int min, int max)
483 1.1 christos {
484 1.1 christos uint32_t result = 0;
485 1.1 christos int len = 0;
486 1.1 christos /* We only want to stop at MAX if we're lexing a byte escape. */
487 1.1 christos int check_max = min == max;
488 1.1 christos
489 1.1 christos while ((check_max ? len <= max : 1)
490 1.1 christos && ((pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'f')
491 1.1 christos || (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'F')
492 1.1 christos || (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9')))
493 1.1 christos {
494 1.1 christos result *= 16;
495 1.1 christos if (pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'f')
496 1.1 christos result = result + 10 + pstate->lexptr[0] - 'a';
497 1.1 christos else if (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'F')
498 1.1 christos result = result + 10 + pstate->lexptr[0] - 'A';
499 1.1 christos else
500 1.1 christos result = result + pstate->lexptr[0] - '0';
501 1.1 christos ++pstate->lexptr;
502 1.1 christos ++len;
503 1.1 christos }
504 1.1 christos
505 1.1 christos if (len < min)
506 1.1 christos error (_("Not enough hex digits seen"));
507 1.1 christos if (len > max)
508 1.1 christos {
509 1.1 christos gdb_assert (min != max);
510 1.1 christos error (_("Overlong hex escape"));
511 1.1 christos }
512 1.1 christos
513 1.1 christos return result;
514 1.1 christos }
515 1.1 christos
516 1.1 christos /* Lex an escape. IS_BYTE is true if we're lexing a byte escape;
517 1.1 christos otherwise we're lexing a character escape. */
518 1.1 christos
519 1.1 christos uint32_t
520 1.1 christos rust_parser::lex_escape (int is_byte)
521 1.1 christos {
522 1.1 christos uint32_t result;
523 1.1 christos
524 1.1 christos gdb_assert (pstate->lexptr[0] == '\\');
525 1.1 christos ++pstate->lexptr;
526 1.1 christos switch (pstate->lexptr[0])
527 1.1 christos {
528 1.1 christos case 'x':
529 1.1 christos ++pstate->lexptr;
530 1.1 christos result = lex_hex (2, 2);
531 1.1 christos break;
532 1.1 christos
533 1.1 christos case 'u':
534 1.1 christos if (is_byte)
535 1.1 christos error (_("Unicode escape in byte literal"));
536 1.1 christos ++pstate->lexptr;
537 1.1 christos if (pstate->lexptr[0] != '{')
538 1.1 christos error (_("Missing '{' in Unicode escape"));
539 1.1 christos ++pstate->lexptr;
540 1.1 christos result = lex_hex (1, 6);
541 1.1 christos /* Could do range checks here. */
542 1.1 christos if (pstate->lexptr[0] != '}')
543 1.1 christos error (_("Missing '}' in Unicode escape"));
544 1.1 christos ++pstate->lexptr;
545 1.1 christos break;
546 1.1 christos
547 1.1 christos case 'n':
548 1.1 christos result = '\n';
549 1.1 christos ++pstate->lexptr;
550 1.1 christos break;
551 1.1 christos case 'r':
552 1.1 christos result = '\r';
553 1.1 christos ++pstate->lexptr;
554 1.1 christos break;
555 1.1 christos case 't':
556 1.1 christos result = '\t';
557 1.1 christos ++pstate->lexptr;
558 1.1 christos break;
559 1.1 christos case '\\':
560 1.1 christos result = '\\';
561 1.1 christos ++pstate->lexptr;
562 1.1 christos break;
563 1.1 christos case '0':
564 1.1 christos result = '\0';
565 1.1 christos ++pstate->lexptr;
566 1.1 christos break;
567 1.1 christos case '\'':
568 1.1 christos result = '\'';
569 1.1 christos ++pstate->lexptr;
570 1.1 christos break;
571 1.1 christos case '"':
572 1.1 christos result = '"';
573 1.1 christos ++pstate->lexptr;
574 1.1 christos break;
575 1.1 christos
576 1.1 christos default:
577 1.1 christos error (_("Invalid escape \\%c in literal"), pstate->lexptr[0]);
578 1.1 christos }
579 1.1 christos
580 1.1 christos return result;
581 1.1 christos }
582 1.1 christos
583 1.1 christos /* A helper for lex_character. Search forward for the closing single
584 1.1 christos quote, then convert the bytes from the host charset to UTF-32. */
585 1.1 christos
586 1.1 christos static uint32_t
587 1.1 christos lex_multibyte_char (const char *text, int *len)
588 1.1 christos {
589 1.1 christos /* Only look a maximum of 5 bytes for the closing quote. This is
590 1.1 christos the maximum for UTF-8. */
591 1.1 christos int quote;
592 1.1 christos gdb_assert (text[0] != '\'');
593 1.1 christos for (quote = 1; text[quote] != '\0' && text[quote] != '\''; ++quote)
594 1.1 christos ;
595 1.1 christos *len = quote;
596 1.1 christos /* The caller will issue an error. */
597 1.1 christos if (text[quote] == '\0')
598 1.1 christos return 0;
599 1.1 christos
600 1.1 christos auto_obstack result;
601 1.1 christos convert_between_encodings (host_charset (), HOST_UTF32,
602 1.1 christos (const gdb_byte *) text,
603 1.1 christos quote, 1, &result, translit_none);
604 1.1 christos
605 1.1 christos int size = obstack_object_size (&result);
606 1.1 christos if (size > 4)
607 1.1 christos error (_("overlong character literal"));
608 1.1 christos uint32_t value;
609 1.1 christos memcpy (&value, obstack_finish (&result), size);
610 1.1 christos return value;
611 1.1 christos }
612 1.1 christos
613 1.1 christos /* Lex a character constant. */
614 1.1 christos
615 1.1 christos int
616 1.1 christos rust_parser::lex_character ()
617 1.1 christos {
618 1.1 christos int is_byte = 0;
619 1.1 christos uint32_t value;
620 1.1 christos
621 1.1 christos if (pstate->lexptr[0] == 'b')
622 1.1 christos {
623 1.1 christos is_byte = 1;
624 1.1 christos ++pstate->lexptr;
625 1.1 christos }
626 1.1 christos gdb_assert (pstate->lexptr[0] == '\'');
627 1.1 christos ++pstate->lexptr;
628 1.1 christos if (pstate->lexptr[0] == '\'')
629 1.1 christos error (_("empty character literal"));
630 1.1 christos else if (pstate->lexptr[0] == '\\')
631 1.1 christos value = lex_escape (is_byte);
632 1.1 christos else
633 1.1 christos {
634 1.1 christos int len;
635 1.1 christos value = lex_multibyte_char (&pstate->lexptr[0], &len);
636 1.1 christos pstate->lexptr += len;
637 1.1 christos }
638 1.1 christos
639 1.1 christos if (pstate->lexptr[0] != '\'')
640 1.1 christos error (_("Unterminated character literal"));
641 1.1 christos ++pstate->lexptr;
642 1.1 christos
643 1.1 christos current_int_val.val = value;
644 1.1 christos current_int_val.type = get_type (is_byte ? "u8" : "char");
645 1.1 christos
646 1.1 christos return INTEGER;
647 1.1 christos }
648 1.1 christos
649 1.1 christos /* Return the offset of the double quote if STR looks like the start
650 1.1 christos of a raw string, or 0 if STR does not start a raw string. */
651 1.1 christos
652 1.1 christos static int
653 1.1 christos starts_raw_string (const char *str)
654 1.1 christos {
655 1.1 christos const char *save = str;
656 1.1 christos
657 1.1 christos if (str[0] != 'r')
658 1.1 christos return 0;
659 1.1 christos ++str;
660 1.1 christos while (str[0] == '#')
661 1.1 christos ++str;
662 1.1 christos if (str[0] == '"')
663 1.1 christos return str - save;
664 1.1 christos return 0;
665 1.1 christos }
666 1.1 christos
667 1.1 christos /* Return true if STR looks like the end of a raw string that had N
668 1.1 christos hashes at the start. */
669 1.1 christos
670 1.1 christos static bool
671 1.1 christos ends_raw_string (const char *str, int n)
672 1.1 christos {
673 1.1 christos int i;
674 1.1 christos
675 1.1 christos gdb_assert (str[0] == '"');
676 1.1 christos for (i = 0; i < n; ++i)
677 1.1 christos if (str[i + 1] != '#')
678 1.1 christos return false;
679 1.1 christos return true;
680 1.1 christos }
681 1.1 christos
682 1.1 christos /* Lex a string constant. */
683 1.1 christos
684 1.1 christos int
685 1.1 christos rust_parser::lex_string ()
686 1.1 christos {
687 1.1 christos int is_byte = pstate->lexptr[0] == 'b';
688 1.1 christos int raw_length;
689 1.1 christos
690 1.1 christos if (is_byte)
691 1.1 christos ++pstate->lexptr;
692 1.1 christos raw_length = starts_raw_string (pstate->lexptr);
693 1.1 christos pstate->lexptr += raw_length;
694 1.1 christos gdb_assert (pstate->lexptr[0] == '"');
695 1.1 christos ++pstate->lexptr;
696 1.1 christos
697 1.1 christos while (1)
698 1.1 christos {
699 1.1 christos uint32_t value;
700 1.1 christos
701 1.1 christos if (raw_length > 0)
702 1.1 christos {
703 1.1 christos if (pstate->lexptr[0] == '"' && ends_raw_string (pstate->lexptr,
704 1.1 christos raw_length - 1))
705 1.1 christos {
706 1.1 christos /* Exit with lexptr pointing after the final "#". */
707 1.1 christos pstate->lexptr += raw_length;
708 1.1 christos break;
709 1.1 christos }
710 1.1 christos else if (pstate->lexptr[0] == '\0')
711 1.1 christos error (_("Unexpected EOF in string"));
712 1.1 christos
713 1.1 christos value = pstate->lexptr[0] & 0xff;
714 1.1 christos if (is_byte && value > 127)
715 1.1 christos error (_("Non-ASCII value in raw byte string"));
716 1.1 christos obstack_1grow (&obstack, value);
717 1.1 christos
718 1.1 christos ++pstate->lexptr;
719 1.1 christos }
720 1.1 christos else if (pstate->lexptr[0] == '"')
721 1.1 christos {
722 1.1 christos /* Make sure to skip the quote. */
723 1.1 christos ++pstate->lexptr;
724 1.1 christos break;
725 1.1 christos }
726 1.1 christos else if (pstate->lexptr[0] == '\\')
727 1.1 christos {
728 1.1 christos value = lex_escape (is_byte);
729 1.1 christos
730 1.1 christos if (is_byte)
731 1.1 christos obstack_1grow (&obstack, value);
732 1.1 christos else
733 1.1 christos convert_between_encodings (HOST_UTF32, "UTF-8",
734 1.1 christos (gdb_byte *) &value,
735 1.1 christos sizeof (value), sizeof (value),
736 1.1 christos &obstack, translit_none);
737 1.1 christos }
738 1.1 christos else if (pstate->lexptr[0] == '\0')
739 1.1 christos error (_("Unexpected EOF in string"));
740 1.1 christos else
741 1.1 christos {
742 1.1 christos value = pstate->lexptr[0] & 0xff;
743 1.1 christos if (is_byte && value > 127)
744 1.1 christos error (_("Non-ASCII value in byte string"));
745 1.1 christos obstack_1grow (&obstack, value);
746 1.1 christos ++pstate->lexptr;
747 1.1 christos }
748 1.1 christos }
749 1.1 christos
750 1.1 christos current_string_val.length = obstack_object_size (&obstack);
751 1.1 christos current_string_val.ptr = (const char *) obstack_finish (&obstack);
752 1.1 christos return is_byte ? BYTESTRING : STRING;
753 1.1 christos }
754 1.1 christos
755 1.1 christos /* Return true if STRING starts with whitespace followed by a digit. */
756 1.1 christos
757 1.1 christos static bool
758 1.1 christos space_then_number (const char *string)
759 1.1 christos {
760 1.1 christos const char *p = string;
761 1.1 christos
762 1.1 christos while (p[0] == ' ' || p[0] == '\t')
763 1.1 christos ++p;
764 1.1 christos if (p == string)
765 1.1 christos return false;
766 1.1 christos
767 1.1 christos return *p >= '0' && *p <= '9';
768 1.1 christos }
769 1.1 christos
770 1.1 christos /* Return true if C can start an identifier. */
771 1.1 christos
772 1.1 christos static bool
773 1.1 christos rust_identifier_start_p (char c)
774 1.1 christos {
775 1.1 christos return ((c >= 'a' && c <= 'z')
776 1.1 christos || (c >= 'A' && c <= 'Z')
777 1.1 christos || c == '_'
778 1.1 christos || c == '$'
779 1.1 christos /* Allow any non-ASCII character as an identifier. There
780 1.1 christos doesn't seem to be a need to be picky about this. */
781 1.1 christos || (c & 0x80) != 0);
782 1.1 christos }
783 1.1 christos
784 1.1 christos /* Lex an identifier. */
785 1.1 christos
786 1.1 christos int
787 1.1 christos rust_parser::lex_identifier ()
788 1.1 christos {
789 1.1 christos unsigned int length;
790 1.1 christos const struct token_info *token;
791 1.1 christos int is_gdb_var = pstate->lexptr[0] == '$';
792 1.1 christos
793 1.1 christos bool is_raw = false;
794 1.1 christos if (pstate->lexptr[0] == 'r'
795 1.1 christos && pstate->lexptr[1] == '#'
796 1.1 christos && rust_identifier_start_p (pstate->lexptr[2]))
797 1.1 christos {
798 1.1 christos is_raw = true;
799 1.1 christos pstate->lexptr += 2;
800 1.1 christos }
801 1.1 christos
802 1.1 christos const char *start = pstate->lexptr;
803 1.1 christos gdb_assert (rust_identifier_start_p (pstate->lexptr[0]));
804 1.1 christos
805 1.1 christos ++pstate->lexptr;
806 1.1 christos
807 1.1 christos /* Allow any non-ASCII character here. This "handles" UTF-8 by
808 1.1 christos passing it through. */
809 1.1 christos while ((pstate->lexptr[0] >= 'a' && pstate->lexptr[0] <= 'z')
810 1.1 christos || (pstate->lexptr[0] >= 'A' && pstate->lexptr[0] <= 'Z')
811 1.1 christos || pstate->lexptr[0] == '_'
812 1.1 christos || (is_gdb_var && pstate->lexptr[0] == '$')
813 1.1 christos || (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9')
814 1.1 christos || (pstate->lexptr[0] & 0x80) != 0)
815 1.1 christos ++pstate->lexptr;
816 1.1 christos
817 1.1 christos
818 1.1 christos length = pstate->lexptr - start;
819 1.1 christos token = NULL;
820 1.1 christos if (!is_raw)
821 1.1 christos {
822 1.1 christos for (const auto &candidate : identifier_tokens)
823 1.1 christos {
824 1.1 christos if (length == strlen (candidate.name)
825 1.1 christos && strncmp (candidate.name, start, length) == 0)
826 1.1 christos {
827 1.1 christos token = &candidate;
828 1.1 christos break;
829 1.1 christos }
830 1.1 christos }
831 1.1 christos }
832 1.1 christos
833 1.1 christos if (token != NULL)
834 1.1 christos {
835 1.1 christos if (token->value == 0)
836 1.1 christos {
837 1.1 christos /* Leave the terminating token alone. */
838 1.1 christos pstate->lexptr = start;
839 1.1 christos return 0;
840 1.1 christos }
841 1.1 christos }
842 1.1 christos else if (token == NULL
843 1.1 christos && !is_raw
844 1.1 christos && (strncmp (start, "thread", length) == 0
845 1.1 christos || strncmp (start, "task", length) == 0)
846 1.1 christos && space_then_number (pstate->lexptr))
847 1.1 christos {
848 1.1 christos /* "task" or "thread" followed by a number terminates the
849 1.1 christos parse, per gdb rules. */
850 1.1 christos pstate->lexptr = start;
851 1.1 christos return 0;
852 1.1 christos }
853 1.1 christos
854 1.1 christos if (token == NULL || (pstate->parse_completion && pstate->lexptr[0] == '\0'))
855 1.1 christos {
856 1.1 christos current_string_val.length = length;
857 1.1 christos current_string_val.ptr = start;
858 1.1 christos }
859 1.1 christos
860 1.1 christos if (pstate->parse_completion && pstate->lexptr[0] == '\0')
861 1.1 christos {
862 1.1 christos /* Prevent rustyylex from returning two COMPLETE tokens. */
863 1.1 christos pstate->prev_lexptr = pstate->lexptr;
864 1.1 christos return COMPLETE;
865 1.1 christos }
866 1.1 christos
867 1.1 christos if (token != NULL)
868 1.1 christos return token->value;
869 1.1 christos if (is_gdb_var)
870 1.1 christos return GDBVAR;
871 1.1 christos return IDENT;
872 1.1 christos }
873 1.1 christos
874 1.1 christos /* Lex an operator. */
875 1.1 christos
876 1.1 christos int
877 1.1 christos rust_parser::lex_operator ()
878 1.1 christos {
879 1.1 christos const struct token_info *token = NULL;
880 1.1 christos
881 1.1 christos for (const auto &candidate : operator_tokens)
882 1.1 christos {
883 1.1 christos if (strncmp (candidate.name, pstate->lexptr,
884 1.1 christos strlen (candidate.name)) == 0)
885 1.1 christos {
886 1.1 christos pstate->lexptr += strlen (candidate.name);
887 1.1 christos token = &candidate;
888 1.1 christos break;
889 1.1 christos }
890 1.1 christos }
891 1.1 christos
892 1.1 christos if (token != NULL)
893 1.1 christos {
894 1.1 christos current_opcode = token->opcode;
895 1.1 christos return token->value;
896 1.1 christos }
897 1.1 christos
898 1.1 christos return *pstate->lexptr++;
899 1.1 christos }
900 1.1 christos
901 1.1 christos /* Lex a number. */
902 1.1 christos
903 1.1 christos int
904 1.1 christos rust_parser::lex_number ()
905 1.1 christos {
906 1.1 christos regmatch_t subexps[NUM_SUBEXPRESSIONS];
907 1.1 christos int match;
908 1.1 christos int is_integer = 0;
909 1.1 christos int could_be_decimal = 1;
910 1.1 christos int implicit_i32 = 0;
911 1.1 christos const char *type_name = NULL;
912 1.1 christos struct type *type;
913 1.1 christos int end_index;
914 1.1 christos int type_index = -1;
915 1.1 christos int i;
916 1.1 christos
917 1.1 christos match = regexec (&number_regex, pstate->lexptr, ARRAY_SIZE (subexps),
918 1.1 christos subexps, 0);
919 1.1 christos /* Failure means the regexp is broken. */
920 1.1 christos gdb_assert (match == 0);
921 1.1 christos
922 1.1 christos if (subexps[INT_TEXT].rm_so != -1)
923 1.1 christos {
924 1.1 christos /* Integer part matched. */
925 1.1 christos is_integer = 1;
926 1.1 christos end_index = subexps[INT_TEXT].rm_eo;
927 1.1 christos if (subexps[INT_TYPE].rm_so == -1)
928 1.1 christos {
929 1.1 christos type_name = "i32";
930 1.1 christos implicit_i32 = 1;
931 1.1 christos }
932 1.1 christos else
933 1.1 christos {
934 1.1 christos type_index = INT_TYPE;
935 1.1 christos could_be_decimal = 0;
936 1.1 christos }
937 1.1 christos }
938 1.1 christos else if (subexps[FLOAT_TYPE1].rm_so != -1)
939 1.1 christos {
940 1.1 christos /* Found floating point type suffix. */
941 1.1 christos end_index = subexps[FLOAT_TYPE1].rm_so;
942 1.1 christos type_index = FLOAT_TYPE1;
943 1.1 christos }
944 1.1 christos else if (subexps[FLOAT_TYPE2].rm_so != -1)
945 1.1 christos {
946 1.1 christos /* Found floating point type suffix. */
947 1.1 christos end_index = subexps[FLOAT_TYPE2].rm_so;
948 1.1 christos type_index = FLOAT_TYPE2;
949 1.1 christos }
950 1.1 christos else
951 1.1 christos {
952 1.1 christos /* Any other floating point match. */
953 1.1 christos end_index = subexps[0].rm_eo;
954 1.1 christos type_name = "f64";
955 1.1 christos }
956 1.1 christos
957 1.1 christos /* We need a special case if the final character is ".". In this
958 1.1 christos case we might need to parse an integer. For example, "23.f()" is
959 1.1 christos a request for a trait method call, not a syntax error involving
960 1.1 christos the floating point number "23.". */
961 1.1 christos gdb_assert (subexps[0].rm_eo > 0);
962 1.1 christos if (pstate->lexptr[subexps[0].rm_eo - 1] == '.')
963 1.1 christos {
964 1.1 christos const char *next = skip_spaces (&pstate->lexptr[subexps[0].rm_eo]);
965 1.1 christos
966 1.1 christos if (rust_identifier_start_p (*next) || *next == '.')
967 1.1 christos {
968 1.1 christos --subexps[0].rm_eo;
969 1.1 christos is_integer = 1;
970 1.1 christos end_index = subexps[0].rm_eo;
971 1.1 christos type_name = "i32";
972 1.1 christos could_be_decimal = 1;
973 1.1 christos implicit_i32 = 1;
974 1.1 christos }
975 1.1 christos }
976 1.1 christos
977 1.1 christos /* Compute the type name if we haven't already. */
978 1.1 christos std::string type_name_holder;
979 1.1 christos if (type_name == NULL)
980 1.1 christos {
981 1.1 christos gdb_assert (type_index != -1);
982 1.1 christos type_name_holder = std::string ((pstate->lexptr
983 1.1 christos + subexps[type_index].rm_so),
984 1.1 christos (subexps[type_index].rm_eo
985 1.1 christos - subexps[type_index].rm_so));
986 1.1 christos type_name = type_name_holder.c_str ();
987 1.1 christos }
988 1.1 christos
989 1.1 christos /* Look up the type. */
990 1.1 christos type = get_type (type_name);
991 1.1 christos
992 1.1 christos /* Copy the text of the number and remove the "_"s. */
993 1.1 christos std::string number;
994 1.1 christos for (i = 0; i < end_index && pstate->lexptr[i]; ++i)
995 1.1 christos {
996 1.1 christos if (pstate->lexptr[i] == '_')
997 1.1 christos could_be_decimal = 0;
998 1.1 christos else
999 1.1 christos number.push_back (pstate->lexptr[i]);
1000 1.1 christos }
1001 1.1 christos
1002 1.1 christos /* Advance past the match. */
1003 1.1 christos pstate->lexptr += subexps[0].rm_eo;
1004 1.1 christos
1005 1.1 christos /* Parse the number. */
1006 1.1 christos if (is_integer)
1007 1.1 christos {
1008 1.1 christos uint64_t value;
1009 1.1 christos int radix = 10;
1010 1.1 christos int offset = 0;
1011 1.1 christos
1012 1.1 christos if (number[0] == '0')
1013 1.1 christos {
1014 1.1 christos if (number[1] == 'x')
1015 1.1 christos radix = 16;
1016 1.1 christos else if (number[1] == 'o')
1017 1.1 christos radix = 8;
1018 1.1 christos else if (number[1] == 'b')
1019 1.1 christos radix = 2;
1020 1.1 christos if (radix != 10)
1021 1.1 christos {
1022 1.1 christos offset = 2;
1023 1.1 christos could_be_decimal = 0;
1024 1.1 christos }
1025 1.1 christos }
1026 1.1 christos
1027 1.1 christos const char *trailer;
1028 1.1 christos value = strtoulst (number.c_str () + offset, &trailer, radix);
1029 1.1 christos if (*trailer != '\0')
1030 1.1 christos error (_("Integer literal is too large"));
1031 1.1 christos if (implicit_i32 && value >= ((uint64_t) 1) << 31)
1032 1.1 christos type = get_type ("i64");
1033 1.1 christos
1034 1.1 christos current_int_val.val = value;
1035 1.1 christos current_int_val.type = type;
1036 1.1 christos }
1037 1.1 christos else
1038 1.1 christos {
1039 1.1 christos current_float_val.type = type;
1040 1.1 christos bool parsed = parse_float (number.c_str (), number.length (),
1041 1.1 christos current_float_val.type,
1042 1.1 christos current_float_val.val.data ());
1043 1.1 christos gdb_assert (parsed);
1044 1.1 christos }
1045 1.1 christos
1046 1.1 christos return is_integer ? (could_be_decimal ? DECIMAL_INTEGER : INTEGER) : FLOAT;
1047 1.1 christos }
1048 1.1 christos
1049 1.1 christos /* The lexer. */
1050 1.1 christos
1051 1.1 christos int
1052 1.1 christos rust_parser::lex_one_token ()
1053 1.1 christos {
1054 1.1 christos /* Skip all leading whitespace. */
1055 1.1 christos while (pstate->lexptr[0] == ' '
1056 1.1 christos || pstate->lexptr[0] == '\t'
1057 1.1 christos || pstate->lexptr[0] == '\r'
1058 1.1 christos || pstate->lexptr[0] == '\n')
1059 1.1 christos ++pstate->lexptr;
1060 1.1 christos
1061 1.1 christos /* If we hit EOF and we're completing, then return COMPLETE -- maybe
1062 1.1 christos we're completing an empty string at the end of a field_expr.
1063 1.1 christos But, we don't want to return two COMPLETE tokens in a row. */
1064 1.1 christos if (pstate->lexptr[0] == '\0' && pstate->lexptr == pstate->prev_lexptr)
1065 1.1 christos return 0;
1066 1.1 christos pstate->prev_lexptr = pstate->lexptr;
1067 1.1 christos if (pstate->lexptr[0] == '\0')
1068 1.1 christos {
1069 1.1 christos if (pstate->parse_completion)
1070 1.1 christos {
1071 1.1 christos current_string_val.length =0;
1072 1.1 christos current_string_val.ptr = "";
1073 1.1 christos return COMPLETE;
1074 1.1 christos }
1075 1.1 christos return 0;
1076 1.1 christos }
1077 1.1 christos
1078 1.1 christos if (pstate->lexptr[0] >= '0' && pstate->lexptr[0] <= '9')
1079 1.1 christos return lex_number ();
1080 1.1 christos else if (pstate->lexptr[0] == 'b' && pstate->lexptr[1] == '\'')
1081 1.1 christos return lex_character ();
1082 1.1 christos else if (pstate->lexptr[0] == 'b' && pstate->lexptr[1] == '"')
1083 1.1 christos return lex_string ();
1084 1.1 christos else if (pstate->lexptr[0] == 'b' && starts_raw_string (pstate->lexptr + 1))
1085 1.1 christos return lex_string ();
1086 1.1 christos else if (starts_raw_string (pstate->lexptr))
1087 1.1 christos return lex_string ();
1088 1.1 christos else if (rust_identifier_start_p (pstate->lexptr[0]))
1089 1.1 christos return lex_identifier ();
1090 1.1 christos else if (pstate->lexptr[0] == '"')
1091 1.1 christos return lex_string ();
1092 1.1 christos else if (pstate->lexptr[0] == '\'')
1093 1.1 christos return lex_character ();
1094 1.1 christos else if (pstate->lexptr[0] == '}' || pstate->lexptr[0] == ']')
1095 1.1 christos {
1096 1.1 christos /* Falls through to lex_operator. */
1097 1.1 christos --paren_depth;
1098 1.1 christos }
1099 1.1 christos else if (pstate->lexptr[0] == '(' || pstate->lexptr[0] == '{')
1100 1.1 christos {
1101 1.1 christos /* Falls through to lex_operator. */
1102 1.1 christos ++paren_depth;
1103 1.1 christos }
1104 1.1 christos else if (pstate->lexptr[0] == ',' && pstate->comma_terminates
1105 1.1 christos && paren_depth == 0)
1106 1.1 christos return 0;
1107 1.1 christos
1108 1.1 christos return lex_operator ();
1109 1.1 christos }
1110 1.1 christos
1111 1.1 christos /* Push back a single character to be re-lexed. */
1112 1.1 christos
1113 1.1 christos void
1114 1.1 christos rust_parser::push_back (char c)
1115 1.1 christos {
1116 1.1 christos /* Can't be called before any lexing. */
1117 1.1 christos gdb_assert (pstate->prev_lexptr != NULL);
1118 1.1 christos
1119 1.1 christos --pstate->lexptr;
1120 1.1 christos gdb_assert (*pstate->lexptr == c);
1121 1.1 christos }
1122 1.1 christos
1123 1.1 christos
1124 1.1 christos
1126 1.1 christos /* Parse a tuple or paren expression. */
1127 1.1 christos
1128 1.1 christos operation_up
1129 1.1 christos rust_parser::parse_tuple ()
1130 1.1 christos {
1131 1.1 christos assume ('(');
1132 1.1 christos
1133 1.1 christos if (current_token == ')')
1134 1.1 christos {
1135 1.1 christos lex ();
1136 1.1 christos struct type *unit = get_type ("()");
1137 1.1 christos return make_operation<long_const_operation> (unit, 0);
1138 1.1 christos }
1139 1.1 christos
1140 1.1 christos operation_up expr = parse_expr ();
1141 1.1 christos if (current_token == ')')
1142 1.1 christos {
1143 1.1 christos /* Parenthesized expression. */
1144 1.1 christos lex ();
1145 1.1 christos return make_operation<rust_parenthesized_operation> (std::move (expr));
1146 1.1 christos }
1147 1.1 christos
1148 1.1 christos std::vector<operation_up> ops;
1149 1.1 christos ops.push_back (std::move (expr));
1150 1.1 christos while (current_token != ')')
1151 1.1 christos {
1152 1.1 christos if (current_token != ',')
1153 1.1 christos error (_("',' or ')' expected"));
1154 1.1 christos lex ();
1155 1.1 christos
1156 1.1 christos /* A trailing "," is ok. */
1157 1.1 christos if (current_token != ')')
1158 1.1 christos ops.push_back (parse_expr ());
1159 1.1 christos }
1160 1.1 christos
1161 1.1 christos assume (')');
1162 1.1 christos
1163 1.1 christos error (_("Tuple expressions not supported yet"));
1164 1.1 christos }
1165 1.1 christos
1166 1.1 christos /* Parse an array expression. */
1167 1.1 christos
1168 1.1 christos operation_up
1169 1.1 christos rust_parser::parse_array ()
1170 1.1 christos {
1171 1.1 christos assume ('[');
1172 1.1 christos
1173 1.1 christos if (current_token == KW_MUT)
1174 1.1 christos lex ();
1175 1.1 christos
1176 1.1 christos operation_up result;
1177 1.1 christos operation_up expr = parse_expr ();
1178 1.1 christos if (current_token == ';')
1179 1.1 christos {
1180 1.1 christos lex ();
1181 1.1 christos operation_up rhs = parse_expr ();
1182 1.1 christos result = make_operation<rust_array_operation> (std::move (expr),
1183 1.1 christos std::move (rhs));
1184 1.1 christos }
1185 1.1 christos else if (current_token == ',')
1186 1.1 christos {
1187 1.1 christos std::vector<operation_up> ops;
1188 1.1 christos ops.push_back (std::move (expr));
1189 1.1 christos while (current_token != ']')
1190 1.1 christos {
1191 1.1 christos if (current_token != ',')
1192 1.1 christos error (_("',' or ']' expected"));
1193 1.1 christos lex ();
1194 1.1 christos ops.push_back (parse_expr ());
1195 1.1 christos }
1196 1.1 christos ops.shrink_to_fit ();
1197 1.1 christos int len = ops.size () - 1;
1198 1.1 christos result = make_operation<array_operation> (0, len, std::move (ops));
1199 1.1 christos }
1200 1.1 christos else if (current_token != ']')
1201 1.1 christos error (_("',', ';', or ']' expected"));
1202 1.1 christos
1203 1.1 christos require (']');
1204 1.1 christos
1205 1.1 christos return result;
1206 1.1 christos }
1207 1.1 christos
1208 1.1 christos /* Turn a name into an operation. */
1209 1.1 christos
1210 1.1 christos operation_up
1211 1.1 christos rust_parser::name_to_operation (const std::string &name)
1212 1.1 christos {
1213 1.1 christos struct block_symbol sym = lookup_symbol (name.c_str (),
1214 1.1 christos pstate->expression_context_block,
1215 1.1 christos VAR_DOMAIN);
1216 1.1 christos if (sym.symbol != nullptr && sym.symbol->aclass () != LOC_TYPEDEF)
1217 1.1 christos return make_operation<var_value_operation> (sym);
1218 1.1 christos
1219 1.1 christos struct type *type = nullptr;
1220 1.1 christos
1221 1.1 christos if (sym.symbol != nullptr)
1222 1.1 christos {
1223 1.1 christos gdb_assert (sym.symbol->aclass () == LOC_TYPEDEF);
1224 1.1 christos type = sym.symbol->type ();
1225 1.1 christos }
1226 1.1 christos if (type == nullptr)
1227 1.1 christos type = rust_lookup_type (name.c_str ());
1228 1.1 christos if (type == nullptr)
1229 1.1 christos error (_("No symbol '%s' in current context"), name.c_str ());
1230 1.1 christos
1231 1.1 christos if (type->code () == TYPE_CODE_STRUCT && type->num_fields () == 0)
1232 1.1 christos {
1233 1.1 christos /* A unit-like struct. */
1234 1.1 christos operation_up result (new rust_aggregate_operation (type, {}, {}));
1235 1.1 christos return result;
1236 1.1 christos }
1237 1.1 christos else
1238 1.1 christos return make_operation<type_operation> (type);
1239 1.1 christos }
1240 1.1 christos
1241 1.1 christos /* Parse a struct expression. */
1242 1.1 christos
1243 1.1 christos operation_up
1244 1.1 christos rust_parser::parse_struct_expr (struct type *type)
1245 1.1 christos {
1246 1.1 christos assume ('{');
1247 1.1 christos
1248 1.1 christos if (type->code () != TYPE_CODE_STRUCT
1249 1.1 christos || rust_tuple_type_p (type)
1250 1.1 christos || rust_tuple_struct_type_p (type))
1251 1.1 christos error (_("Struct expression applied to non-struct type"));
1252 1.1 christos
1253 1.1 christos std::vector<std::pair<std::string, operation_up>> field_v;
1254 1.1 christos while (current_token != '}' && current_token != DOTDOT)
1255 1.1 christos {
1256 1.1 christos if (current_token != IDENT)
1257 1.1 christos error (_("'}', '..', or identifier expected"));
1258 1.1 christos
1259 1.1 christos std::string name = get_string ();
1260 1.1 christos lex ();
1261 1.1 christos
1262 1.1 christos operation_up expr;
1263 1.1 christos if (current_token == ',' || current_token == '}'
1264 1.1 christos || current_token == DOTDOT)
1265 1.1 christos expr = name_to_operation (name);
1266 1.1 christos else
1267 1.1 christos {
1268 1.1 christos require (':');
1269 1.1 christos expr = parse_expr ();
1270 1.1 christos }
1271 1.1 christos field_v.emplace_back (std::move (name), std::move (expr));
1272 1.1 christos
1273 1.1 christos /* A trailing "," is ok. */
1274 1.1 christos if (current_token == ',')
1275 1.1 christos lex ();
1276 1.1 christos }
1277 1.1 christos
1278 1.1 christos operation_up others;
1279 1.1 christos if (current_token == DOTDOT)
1280 1.1 christos {
1281 1.1 christos lex ();
1282 1.1 christos others = parse_expr ();
1283 1.1 christos }
1284 1.1 christos
1285 1.1 christos require ('}');
1286 1.1 christos
1287 1.1 christos return make_operation<rust_aggregate_operation> (type,
1288 1.1 christos std::move (others),
1289 1.1 christos std::move (field_v));
1290 1.1 christos }
1291 1.1 christos
1292 1.1 christos /* Used by the operator precedence parser. */
1293 1.1 christos struct rustop_item
1294 1.1 christos {
1295 1.1 christos rustop_item (int token_, int precedence_, enum exp_opcode opcode_,
1296 1.1 christos operation_up &&op_)
1297 1.1 christos : token (token_),
1298 1.1 christos precedence (precedence_),
1299 1.1 christos opcode (opcode_),
1300 1.1 christos op (std::move (op_))
1301 1.1 christos {
1302 1.1 christos }
1303 1.1 christos
1304 1.1 christos /* The token value. */
1305 1.1 christos int token;
1306 1.1 christos /* Precedence of this operator. */
1307 1.1 christos int precedence;
1308 1.1 christos /* This is used only for assign-modify. */
1309 1.1 christos enum exp_opcode opcode;
1310 1.1 christos /* The right hand side of this operation. */
1311 1.1 christos operation_up op;
1312 1.1 christos };
1313 1.1 christos
1314 1.1 christos /* An operator precedence parser for binary operations, including
1315 1.1 christos "as". */
1316 1.1 christos
1317 1.1 christos operation_up
1318 1.1 christos rust_parser::parse_binop (bool required)
1319 1.1 christos {
1320 1.1 christos /* All the binary operators. Each one is of the form
1321 1.1 christos OPERATION(TOKEN, PRECEDENCE, TYPE)
1322 1.1 christos TOKEN is the corresponding operator token.
1323 1.1 christos PRECEDENCE is a value indicating relative precedence.
1324 1.1 christos TYPE is the operation type corresponding to the operator.
1325 1.1 christos Assignment operations are handled specially, not via this
1326 1.1 christos table; they have precedence 0. */
1327 1.1 christos #define ALL_OPS \
1328 1.1 christos OPERATION ('*', 10, mul_operation) \
1329 1.1 christos OPERATION ('/', 10, div_operation) \
1330 1.1 christos OPERATION ('%', 10, rem_operation) \
1331 1.1 christos OPERATION ('@', 9, repeat_operation) \
1332 1.1 christos OPERATION ('+', 8, add_operation) \
1333 1.1 christos OPERATION ('-', 8, sub_operation) \
1334 1.1 christos OPERATION (LSH, 7, lsh_operation) \
1335 1.1 christos OPERATION (RSH, 7, rsh_operation) \
1336 1.1 christos OPERATION ('&', 6, bitwise_and_operation) \
1337 1.1 christos OPERATION ('^', 5, bitwise_xor_operation) \
1338 1.1 christos OPERATION ('|', 4, bitwise_ior_operation) \
1339 1.1 christos OPERATION (EQEQ, 3, equal_operation) \
1340 1.1 christos OPERATION (NOTEQ, 3, notequal_operation) \
1341 1.1 christos OPERATION ('<', 3, less_operation) \
1342 1.1 christos OPERATION (LTEQ, 3, leq_operation) \
1343 1.1 christos OPERATION ('>', 3, gtr_operation) \
1344 1.1 christos OPERATION (GTEQ, 3, geq_operation) \
1345 1.1 christos OPERATION (ANDAND, 2, logical_and_operation) \
1346 1.1 christos OPERATION (OROR, 1, logical_or_operation)
1347 1.1 christos
1348 1.1 christos #define ASSIGN_PREC 0
1349 1.1 christos
1350 1.1 christos operation_up start = parse_atom (required);
1351 1.1 christos if (start == nullptr)
1352 1.1 christos {
1353 1.1 christos gdb_assert (!required);
1354 1.1 christos return start;
1355 1.1 christos }
1356 1.1 christos
1357 1.1 christos std::vector<rustop_item> operator_stack;
1358 1.1 christos operator_stack.emplace_back (0, -1, OP_NULL, std::move (start));
1359 1.1 christos
1360 1.1 christos while (true)
1361 1.1 christos {
1362 1.1 christos int this_token = current_token;
1363 1.1 christos enum exp_opcode compound_assign_op = OP_NULL;
1364 1.1 christos int precedence = -2;
1365 1.1 christos
1366 1.1 christos switch (this_token)
1367 1.1 christos {
1368 1.1 christos #define OPERATION(TOKEN, PRECEDENCE, TYPE) \
1369 1.1 christos case TOKEN: \
1370 1.1 christos precedence = PRECEDENCE; \
1371 1.1 christos lex (); \
1372 1.1 christos break;
1373 1.1 christos
1374 1.1 christos ALL_OPS
1375 1.1 christos
1376 1.1 christos #undef OPERATION
1377 1.1 christos
1378 1.1 christos case COMPOUND_ASSIGN:
1379 1.1 christos compound_assign_op = current_opcode;
1380 1.1 christos /* FALLTHROUGH */
1381 1.1 christos case '=':
1382 1.1 christos precedence = ASSIGN_PREC;
1383 1.1 christos lex ();
1384 1.1 christos break;
1385 1.1 christos
1386 1.1 christos /* "as" must be handled specially. */
1387 1.1 christos case KW_AS:
1388 1.1 christos {
1389 1.1 christos lex ();
1390 1.1 christos rustop_item &lhs = operator_stack.back ();
1391 1.1 christos struct type *type = parse_type ();
1392 1.1 christos lhs.op = make_operation<unop_cast_operation> (std::move (lhs.op),
1393 1.1 christos type);
1394 1.1 christos }
1395 1.1 christos /* Bypass the rest of the loop. */
1396 1.1 christos continue;
1397 1.1 christos
1398 1.1 christos default:
1399 1.1 christos /* Arrange to pop the entire stack. */
1400 1.1 christos precedence = -2;
1401 1.1 christos break;
1402 1.1 christos }
1403 1.1 christos
1404 1.1 christos /* Make sure that assignments are right-associative while other
1405 1.1 christos operations are left-associative. */
1406 1.1 christos while ((precedence == ASSIGN_PREC
1407 1.1 christos ? precedence < operator_stack.back ().precedence
1408 1.1 christos : precedence <= operator_stack.back ().precedence)
1409 1.1 christos && operator_stack.size () > 1)
1410 1.1 christos {
1411 1.1 christos rustop_item rhs = std::move (operator_stack.back ());
1412 1.1 christos operator_stack.pop_back ();
1413 1.1 christos
1414 1.1 christos rustop_item &lhs = operator_stack.back ();
1415 1.1 christos
1416 1.1 christos switch (rhs.token)
1417 1.1 christos {
1418 1.1 christos #define OPERATION(TOKEN, PRECEDENCE, TYPE) \
1419 1.1 christos case TOKEN: \
1420 1.1 christos lhs.op = make_operation<TYPE> (std::move (lhs.op), \
1421 1.1 christos std::move (rhs.op)); \
1422 1.1 christos break;
1423 1.1 christos
1424 1.1 christos ALL_OPS
1425 1.1 christos
1426 1.1 christos #undef OPERATION
1427 1.1 christos
1428 1.1 christos case '=':
1429 1.1 christos case COMPOUND_ASSIGN:
1430 1.1 christos {
1431 1.1 christos if (rhs.token == '=')
1432 1.1 christos lhs.op = (make_operation<assign_operation>
1433 1.1 christos (std::move (lhs.op), std::move (rhs.op)));
1434 1.1 christos else
1435 1.1 christos lhs.op = (make_operation<assign_modify_operation>
1436 1.1 christos (rhs.opcode, std::move (lhs.op),
1437 1.1 christos std::move (rhs.op)));
1438 1.1 christos
1439 1.1 christos struct type *unit_type = get_type ("()");
1440 1.1 christos
1441 1.1 christos operation_up nil (new long_const_operation (unit_type, 0));
1442 1.1 christos lhs.op = (make_operation<comma_operation>
1443 1.1 christos (std::move (lhs.op), std::move (nil)));
1444 1.1 christos }
1445 1.1 christos break;
1446 1.1 christos
1447 1.1 christos default:
1448 1.1 christos gdb_assert_not_reached ("bad binary operator");
1449 1.1 christos }
1450 1.1 christos }
1451 1.1 christos
1452 1.1 christos if (precedence == -2)
1453 1.1 christos break;
1454 1.1 christos
1455 1.1 christos operator_stack.emplace_back (this_token, precedence, compound_assign_op,
1456 1.1 christos parse_atom (true));
1457 1.1 christos }
1458 1.1 christos
1459 1.1 christos gdb_assert (operator_stack.size () == 1);
1460 1.1 christos return std::move (operator_stack[0].op);
1461 1.1 christos #undef ALL_OPS
1462 1.1 christos }
1463 1.1 christos
1464 1.1 christos /* Parse a range expression. */
1465 1.1 christos
1466 1.1 christos operation_up
1467 1.1 christos rust_parser::parse_range ()
1468 1.1 christos {
1469 1.1 christos enum range_flag kind = (RANGE_HIGH_BOUND_DEFAULT
1470 1.1 christos | RANGE_LOW_BOUND_DEFAULT);
1471 1.1 christos
1472 1.1 christos operation_up lhs;
1473 1.1 christos if (current_token != DOTDOT && current_token != DOTDOTEQ)
1474 1.1 christos {
1475 1.1 christos lhs = parse_binop (true);
1476 1.1 christos kind &= ~RANGE_LOW_BOUND_DEFAULT;
1477 1.1 christos }
1478 1.1 christos
1479 1.1 christos if (current_token == DOTDOT)
1480 1.1 christos kind |= RANGE_HIGH_BOUND_EXCLUSIVE;
1481 1.1 christos else if (current_token != DOTDOTEQ)
1482 1.1 christos return lhs;
1483 1.1 christos lex ();
1484 1.1 christos
1485 1.1 christos /* A "..=" range requires a high bound, but otherwise it is
1486 1.1 christos optional. */
1487 1.1 christos operation_up rhs = parse_binop ((kind & RANGE_HIGH_BOUND_EXCLUSIVE) == 0);
1488 1.1 christos if (rhs != nullptr)
1489 1.1 christos kind &= ~RANGE_HIGH_BOUND_DEFAULT;
1490 1.1 christos
1491 1.1 christos return make_operation<rust_range_operation> (kind,
1492 1.1 christos std::move (lhs),
1493 1.1 christos std::move (rhs));
1494 1.1 christos }
1495 1.1 christos
1496 1.1 christos /* Parse an expression. */
1497 1.1 christos
1498 1.1 christos operation_up
1499 1.1 christos rust_parser::parse_expr ()
1500 1.1 christos {
1501 1.1 christos return parse_range ();
1502 1.1 christos }
1503 1.1 christos
1504 1.1 christos /* Parse a sizeof expression. */
1505 1.1 christos
1506 1.1 christos operation_up
1507 1.1 christos rust_parser::parse_sizeof ()
1508 1.1 christos {
1509 1.1 christos assume (KW_SIZEOF);
1510 1.1 christos
1511 1.1 christos require ('(');
1512 1.1 christos operation_up result = make_operation<unop_sizeof_operation> (parse_expr ());
1513 1.1 christos require (')');
1514 1.1 christos return result;
1515 1.1 christos }
1516 1.1 christos
1517 1.1 christos /* Parse an address-of operation. */
1518 1.1 christos
1519 1.1 christos operation_up
1520 1.1 christos rust_parser::parse_addr ()
1521 1.1 christos {
1522 1.1 christos assume ('&');
1523 1.1 christos
1524 1.1 christos if (current_token == KW_MUT)
1525 1.1 christos lex ();
1526 1.1 christos
1527 1.1 christos return make_operation<rust_unop_addr_operation> (parse_atom (true));
1528 1.1 christos }
1529 1.1 christos
1530 1.1 christos /* Parse a field expression. */
1531 1.1 christos
1532 1.1 christos operation_up
1533 1.1 christos rust_parser::parse_field (operation_up &&lhs)
1534 1.1 christos {
1535 1.1 christos assume ('.');
1536 1.1 christos
1537 1.1 christos operation_up result;
1538 1.1 christos switch (current_token)
1539 1.1 christos {
1540 1.1 christos case IDENT:
1541 1.1 christos case COMPLETE:
1542 1.1 christos {
1543 1.1 christos bool is_complete = current_token == COMPLETE;
1544 1.1 christos auto struct_op = new rust_structop (std::move (lhs), get_string ());
1545 1.1 christos lex ();
1546 1.1 christos if (is_complete)
1547 1.1 christos {
1548 1.1 christos completion_op.reset (struct_op);
1549 1.1 christos pstate->mark_struct_expression (struct_op);
1550 1.1 christos /* Throw to the outermost level of the parser. */
1551 1.1 christos error (_("not really an error"));
1552 1.1 christos }
1553 1.1 christos result.reset (struct_op);
1554 1.1 christos }
1555 1.1 christos break;
1556 1.1 christos
1557 1.1 christos case DECIMAL_INTEGER:
1558 1.1 christos result = make_operation<rust_struct_anon> (current_int_val.val,
1559 1.1 christos std::move (lhs));
1560 1.1 christos lex ();
1561 1.1 christos break;
1562 1.1 christos
1563 1.1 christos case INTEGER:
1564 1.1 christos error (_("'_' not allowed in integers in anonymous field references"));
1565 1.1 christos
1566 1.1 christos default:
1567 1.1 christos error (_("field name expected"));
1568 1.1 christos }
1569 1.1 christos
1570 1.1 christos return result;
1571 1.1 christos }
1572 1.1 christos
1573 1.1 christos /* Parse an index expression. */
1574 1.1 christos
1575 1.1 christos operation_up
1576 1.1 christos rust_parser::parse_index (operation_up &&lhs)
1577 1.1 christos {
1578 1.1 christos assume ('[');
1579 1.1 christos operation_up rhs = parse_expr ();
1580 1.1 christos require (']');
1581 1.1 christos
1582 1.1 christos return make_operation<rust_subscript_operation> (std::move (lhs),
1583 1.1 christos std::move (rhs));
1584 1.1 christos }
1585 1.1 christos
1586 1.1 christos /* Parse a sequence of comma-separated expressions in parens. */
1587 1.1 christos
1588 1.1 christos std::vector<operation_up>
1589 1.1 christos rust_parser::parse_paren_args ()
1590 1.1 christos {
1591 1.1 christos assume ('(');
1592 1.1 christos
1593 1.1 christos std::vector<operation_up> args;
1594 1.1 christos while (current_token != ')')
1595 1.1 christos {
1596 1.1 christos if (!args.empty ())
1597 1.1 christos {
1598 1.1 christos if (current_token != ',')
1599 1.1 christos error (_("',' or ')' expected"));
1600 1.1 christos lex ();
1601 1.1 christos }
1602 1.1 christos
1603 1.1 christos args.push_back (parse_expr ());
1604 1.1 christos }
1605 1.1 christos
1606 1.1 christos assume (')');
1607 1.1 christos
1608 1.1 christos return args;
1609 1.1 christos }
1610 1.1 christos
1611 1.1 christos /* Parse the parenthesized part of a function call. */
1612 1.1 christos
1613 1.1 christos operation_up
1614 1.1 christos rust_parser::parse_call (operation_up &&lhs)
1615 1.1 christos {
1616 1.1 christos std::vector<operation_up> args = parse_paren_args ();
1617 1.1 christos
1618 1.1 christos return make_operation<funcall_operation> (std::move (lhs),
1619 1.1 christos std::move (args));
1620 1.1 christos }
1621 1.1 christos
1622 1.1 christos /* Parse a list of types. */
1623 1.1 christos
1624 1.1 christos std::vector<struct type *>
1625 1.1 christos rust_parser::parse_type_list ()
1626 1.1 christos {
1627 1.1 christos std::vector<struct type *> result;
1628 1.1 christos result.push_back (parse_type ());
1629 1.1 christos while (current_token == ',')
1630 1.1 christos {
1631 1.1 christos lex ();
1632 1.1 christos result.push_back (parse_type ());
1633 1.1 christos }
1634 1.1 christos return result;
1635 1.1 christos }
1636 1.1 christos
1637 1.1 christos /* Parse a possibly-empty list of types, surrounded in parens. */
1638 1.1 christos
1639 1.1 christos std::vector<struct type *>
1640 1.1 christos rust_parser::parse_maybe_type_list ()
1641 1.1 christos {
1642 1.1 christos assume ('(');
1643 1.1 christos std::vector<struct type *> types;
1644 1.1 christos if (current_token != ')')
1645 1.1 christos types = parse_type_list ();
1646 1.1 christos require (')');
1647 1.1 christos return types;
1648 1.1 christos }
1649 1.1 christos
1650 1.1 christos /* Parse an array type. */
1651 1.1 christos
1652 1.1 christos struct type *
1653 1.1 christos rust_parser::parse_array_type ()
1654 1.1 christos {
1655 1.1 christos assume ('[');
1656 1.1 christos struct type *elt_type = parse_type ();
1657 1.1 christos require (';');
1658 1.1 christos
1659 1.1 christos if (current_token != INTEGER && current_token != DECIMAL_INTEGER)
1660 1.1 christos error (_("integer expected"));
1661 1.1 christos ULONGEST val = current_int_val.val;
1662 1.1 christos lex ();
1663 1.1 christos require (']');
1664 1.1 christos
1665 1.1 christos return lookup_array_range_type (elt_type, 0, val - 1);
1666 1.1 christos }
1667 1.1 christos
1668 1.1 christos /* Parse a slice type. */
1669 1.1 christos
1670 1.1 christos struct type *
1671 1.1 christos rust_parser::parse_slice_type ()
1672 1.1 christos {
1673 1.1 christos assume ('&');
1674 1.1 christos
1675 1.1 christos bool is_slice = current_token == '[';
1676 1.1 christos if (is_slice)
1677 1.1 christos lex ();
1678 1.1 christos
1679 1.1 christos struct type *target = parse_type ();
1680 1.1 christos
1681 1.1 christos if (is_slice)
1682 1.1 christos {
1683 1.1 christos require (']');
1684 1.1 christos return rust_slice_type ("&[*gdb*]", target, get_type ("usize"));
1685 1.1 christos }
1686 1.1 christos
1687 1.1 christos /* For now we treat &x and *x identically. */
1688 1.1 christos return lookup_pointer_type (target);
1689 1.1 christos }
1690 1.1 christos
1691 1.1 christos /* Parse a pointer type. */
1692 1.1 christos
1693 1.1 christos struct type *
1694 1.1 christos rust_parser::parse_pointer_type ()
1695 1.1 christos {
1696 1.1 christos assume ('*');
1697 1.1 christos
1698 1.1 christos if (current_token == KW_MUT || current_token == KW_CONST)
1699 1.1 christos lex ();
1700 1.1 christos
1701 1.1 christos struct type *target = parse_type ();
1702 1.1 christos /* For the time being we ignore mut/const. */
1703 1.1 christos return lookup_pointer_type (target);
1704 1.1 christos }
1705 1.1 christos
1706 1.1 christos /* Parse a function type. */
1707 1.1 christos
1708 1.1 christos struct type *
1709 1.1 christos rust_parser::parse_function_type ()
1710 1.1 christos {
1711 1.1 christos assume (KW_FN);
1712 1.1 christos
1713 1.1 christos if (current_token != '(')
1714 1.1 christos error (_("'(' expected"));
1715 1.1 christos
1716 1.1 christos std::vector<struct type *> types = parse_maybe_type_list ();
1717 1.1 christos
1718 1.1 christos if (current_token != ARROW)
1719 1.1 christos error (_("'->' expected"));
1720 1.1 christos lex ();
1721 1.1 christos
1722 1.1 christos struct type *result_type = parse_type ();
1723 1.1 christos
1724 1.1 christos struct type **argtypes = nullptr;
1725 1.1 christos if (!types.empty ())
1726 1.1 christos argtypes = types.data ();
1727 1.1 christos
1728 1.1 christos result_type = lookup_function_type_with_arguments (result_type,
1729 1.1 christos types.size (),
1730 1.1 christos argtypes);
1731 1.1 christos return lookup_pointer_type (result_type);
1732 1.1 christos }
1733 1.1 christos
1734 1.1 christos /* Parse a tuple type. */
1735 1.1 christos
1736 1.1 christos struct type *
1737 1.1 christos rust_parser::parse_tuple_type ()
1738 1.1 christos {
1739 1.1 christos std::vector<struct type *> types = parse_maybe_type_list ();
1740 1.1 christos
1741 1.1 christos auto_obstack obstack;
1742 1.1 christos obstack_1grow (&obstack, '(');
1743 1.1 christos for (int i = 0; i < types.size (); ++i)
1744 1.1 christos {
1745 1.1 christos std::string type_name = type_to_string (types[i]);
1746 1.1 christos
1747 1.1 christos if (i > 0)
1748 1.1 christos obstack_1grow (&obstack, ',');
1749 1.1 christos obstack_grow_str (&obstack, type_name.c_str ());
1750 1.1 christos }
1751 1.1 christos
1752 1.1 christos obstack_grow_str0 (&obstack, ")");
1753 1.1 christos const char *name = (const char *) obstack_finish (&obstack);
1754 1.1 christos
1755 1.1 christos /* We don't allow creating new tuple types (yet), but we do allow
1756 1.1 christos looking up existing tuple types. */
1757 1.1 christos struct type *result = rust_lookup_type (name);
1758 1.1 christos if (result == nullptr)
1759 1.1 christos error (_("could not find tuple type '%s'"), name);
1760 1.1 christos
1761 1.1 christos return result;
1762 1.1 christos }
1763 1.1 christos
1764 1.1 christos /* Parse a type. */
1765 1.1 christos
1766 1.1 christos struct type *
1767 1.1 christos rust_parser::parse_type ()
1768 1.1 christos {
1769 1.1 christos switch (current_token)
1770 1.1 christos {
1771 1.1 christos case '[':
1772 1.1 christos return parse_array_type ();
1773 1.1 christos case '&':
1774 1.1 christos return parse_slice_type ();
1775 1.1 christos case '*':
1776 1.1 christos return parse_pointer_type ();
1777 1.1 christos case KW_FN:
1778 1.1 christos return parse_function_type ();
1779 1.1 christos case '(':
1780 1.1 christos return parse_tuple_type ();
1781 1.1 christos case KW_SELF:
1782 1.1 christos case KW_SUPER:
1783 1.1 christos case COLONCOLON:
1784 1.1 christos case KW_EXTERN:
1785 1.1 christos case IDENT:
1786 1.1 christos {
1787 1.1 christos std::string path = parse_path (false);
1788 1.1 christos struct type *result = rust_lookup_type (path.c_str ());
1789 1.1 christos if (result == nullptr)
1790 1.1 christos error (_("No type name '%s' in current context"), path.c_str ());
1791 1.1 christos return result;
1792 1.1 christos }
1793 1.1 christos default:
1794 1.1 christos error (_("type expected"));
1795 1.1 christos }
1796 1.1 christos }
1797 1.1 christos
1798 1.1 christos /* Parse a path. */
1799 1.1 christos
1800 1.1 christos std::string
1801 1.1 christos rust_parser::parse_path (bool for_expr)
1802 1.1 christos {
1803 1.1 christos unsigned n_supers = 0;
1804 1.1 christos int first_token = current_token;
1805 1.1 christos
1806 1.1 christos switch (current_token)
1807 1.1 christos {
1808 1.1 christos case KW_SELF:
1809 1.1 christos lex ();
1810 1.1 christos if (current_token != COLONCOLON)
1811 1.1 christos return "self";
1812 1.1 christos lex ();
1813 1.1 christos /* FALLTHROUGH */
1814 1.1 christos case KW_SUPER:
1815 1.1 christos while (current_token == KW_SUPER)
1816 1.1 christos {
1817 1.1 christos ++n_supers;
1818 1.1 christos lex ();
1819 1.1 christos if (current_token != COLONCOLON)
1820 1.1 christos error (_("'::' expected"));
1821 1.1 christos lex ();
1822 1.1 christos }
1823 1.1 christos break;
1824 1.1 christos
1825 1.1 christos case COLONCOLON:
1826 1.1 christos lex ();
1827 1.1 christos break;
1828 1.1 christos
1829 1.1 christos case KW_EXTERN:
1830 1.1 christos /* This is a gdb extension to make it possible to refer to items
1831 1.1 christos in other crates. It just bypasses adding the current crate
1832 1.1 christos to the front of the name. */
1833 1.1 christos lex ();
1834 1.1 christos break;
1835 1.1 christos }
1836 1.1 christos
1837 1.1 christos if (current_token != IDENT)
1838 1.1 christos error (_("identifier expected"));
1839 1.1 christos std::string path = get_string ();
1840 1.1 christos bool saw_ident = true;
1841 1.1 christos lex ();
1842 1.1 christos
1843 1.1 christos /* The condition here lets us enter the loop even if we see
1844 1.1 christos "ident<...>". */
1845 1.1 christos while (current_token == COLONCOLON || current_token == '<')
1846 1.1 christos {
1847 1.1 christos if (current_token == COLONCOLON)
1848 1.1 christos {
1849 1.1 christos lex ();
1850 1.1 christos saw_ident = false;
1851 1.1 christos
1852 1.1 christos if (current_token == IDENT)
1853 1.1 christos {
1854 1.1 christos path = path + "::" + get_string ();
1855 1.1 christos lex ();
1856 1.1 christos saw_ident = true;
1857 1.1 christos }
1858 1.1 christos else if (current_token == COLONCOLON)
1859 1.1 christos {
1860 1.1 christos /* The code below won't detect this scenario. */
1861 1.1 christos error (_("unexpected '::'"));
1862 1.1 christos }
1863 1.1 christos }
1864 1.1 christos
1865 1.1 christos if (current_token != '<')
1866 1.1 christos continue;
1867 1.1 christos
1868 1.1 christos /* Expression use name::<...>, whereas types use name<...>. */
1869 1.1 christos if (for_expr)
1870 1.1 christos {
1871 1.1 christos /* Expressions use "name::<...>", so if we saw an identifier
1872 1.1 christos after the "::", we ignore the "<" here. */
1873 1.1 christos if (saw_ident)
1874 1.1 christos break;
1875 1.1 christos }
1876 1.1 christos else
1877 1.1 christos {
1878 1.1 christos /* Types use "name<...>", so we need to have seen the
1879 1.1 christos identifier. */
1880 1.1 christos if (!saw_ident)
1881 1.1 christos break;
1882 1.1 christos }
1883 1.1 christos
1884 1.1 christos lex ();
1885 1.1 christos std::vector<struct type *> types = parse_type_list ();
1886 1.1 christos if (current_token == '>')
1887 1.1 christos lex ();
1888 1.1 christos else if (current_token == RSH)
1889 1.1 christos {
1890 1.1 christos push_back ('>');
1891 1.1 christos lex ();
1892 1.1 christos }
1893 1.1 christos else
1894 1.1 christos error (_("'>' expected"));
1895 1.1 christos
1896 1.1 christos path += "<";
1897 1.1 christos for (int i = 0; i < types.size (); ++i)
1898 1.1 christos {
1899 1.1 christos if (i > 0)
1900 1.1 christos path += ",";
1901 1.1 christos path += type_to_string (types[i]);
1902 1.1 christos }
1903 1.1 christos path += ">";
1904 1.1 christos break;
1905 1.1 christos }
1906 1.1 christos
1907 1.1 christos switch (first_token)
1908 1.1 christos {
1909 1.1 christos case KW_SELF:
1910 1.1 christos case KW_SUPER:
1911 1.1 christos return super_name (path, n_supers);
1912 1.1 christos
1913 1.1 christos case COLONCOLON:
1914 1.1 christos return crate_name (path);
1915 1.1 christos
1916 1.1 christos case KW_EXTERN:
1917 1.1 christos return "::" + path;
1918 1.1 christos
1919 1.1 christos case IDENT:
1920 1.1 christos return path;
1921 1.1 christos
1922 1.1 christos default:
1923 1.1 christos gdb_assert_not_reached ("missing case in path parsing");
1924 1.1 christos }
1925 1.1 christos }
1926 1.1 christos
1927 1.1 christos /* Handle the parsing for a string expression. */
1928 1.1 christos
1929 1.1 christos operation_up
1930 1.1 christos rust_parser::parse_string ()
1931 1.1 christos {
1932 1.1 christos gdb_assert (current_token == STRING);
1933 1.1 christos
1934 1.1 christos /* Wrap the raw string in the &str struct. */
1935 1.1 christos struct type *type = rust_lookup_type ("&str");
1936 1.1 christos if (type == nullptr)
1937 1.1 christos error (_("Could not find type '&str'"));
1938 1.1 christos
1939 1.1 christos std::vector<std::pair<std::string, operation_up>> field_v;
1940 1.1 christos
1941 1.1 christos size_t len = current_string_val.length;
1942 1.1 christos operation_up str = make_operation<string_operation> (get_string ());
1943 1.1 christos operation_up addr
1944 1.1 christos = make_operation<rust_unop_addr_operation> (std::move (str));
1945 1.1 christos field_v.emplace_back ("data_ptr", std::move (addr));
1946 1.1 christos
1947 1.1 christos struct type *valtype = get_type ("usize");
1948 1.1 christos operation_up lenop = make_operation<long_const_operation> (valtype, len);
1949 1.1 christos field_v.emplace_back ("length", std::move (lenop));
1950 1.1 christos
1951 1.1 christos return make_operation<rust_aggregate_operation> (type,
1952 1.1 christos operation_up (),
1953 1.1 christos std::move (field_v));
1954 1.1 christos }
1955 1.1 christos
1956 1.1 christos /* Parse a tuple struct expression. */
1957 1.1 christos
1958 1.1 christos operation_up
1959 1.1 christos rust_parser::parse_tuple_struct (struct type *type)
1960 1.1 christos {
1961 1.1 christos std::vector<operation_up> args = parse_paren_args ();
1962 1.1 christos
1963 1.1 christos std::vector<std::pair<std::string, operation_up>> field_v (args.size ());
1964 1.1 christos for (int i = 0; i < args.size (); ++i)
1965 1.1 christos field_v[i] = { string_printf ("__%d", i), std::move (args[i]) };
1966 1.1 christos
1967 1.1 christos return (make_operation<rust_aggregate_operation>
1968 1.1 christos (type, operation_up (), std::move (field_v)));
1969 1.1 christos }
1970 1.1 christos
1971 1.1 christos /* Parse a path expression. */
1972 1.1 christos
1973 1.1 christos operation_up
1974 1.1 christos rust_parser::parse_path_expr ()
1975 1.1 christos {
1976 1.1 christos std::string path = parse_path (true);
1977 1.1 christos
1978 1.1 christos if (current_token == '{')
1979 1.1 christos {
1980 1.1 christos struct type *type = rust_lookup_type (path.c_str ());
1981 1.1 christos if (type == nullptr)
1982 1.1 christos error (_("Could not find type '%s'"), path.c_str ());
1983 1.1 christos
1984 1.1 christos return parse_struct_expr (type);
1985 1.1 christos }
1986 1.1 christos else if (current_token == '(')
1987 1.1 christos {
1988 1.1 christos struct type *type = rust_lookup_type (path.c_str ());
1989 1.1 christos /* If this is actually a tuple struct expression, handle it
1990 1.1 christos here. If it is a call, it will be handled elsewhere. */
1991 1.1 christos if (type != nullptr)
1992 1.1 christos {
1993 1.1 christos if (!rust_tuple_struct_type_p (type))
1994 1.1 christos error (_("Type %s is not a tuple struct"), path.c_str ());
1995 1.1 christos return parse_tuple_struct (type);
1996 1.1 christos }
1997 1.1 christos }
1998 1.1 christos
1999 1.1 christos return name_to_operation (path);
2000 1.1 christos }
2001 1.1 christos
2002 1.1 christos /* Parse an atom. "Atom" isn't a Rust term, but this refers to a
2003 1.1 christos single unitary item in the grammar; but here including some unary
2004 1.1 christos prefix and postfix expressions. */
2005 1.1 christos
2006 1.1 christos operation_up
2007 1.1 christos rust_parser::parse_atom (bool required)
2008 1.1 christos {
2009 1.1 christos operation_up result;
2010 1.1 christos
2011 1.1 christos switch (current_token)
2012 1.1 christos {
2013 1.1 christos case '(':
2014 1.1 christos result = parse_tuple ();
2015 1.1 christos break;
2016 1.1 christos
2017 1.1 christos case '[':
2018 1.1 christos result = parse_array ();
2019 1.1 christos break;
2020 1.1 christos
2021 1.1 christos case INTEGER:
2022 1.1 christos case DECIMAL_INTEGER:
2023 1.1 christos result = make_operation<long_const_operation> (current_int_val.type,
2024 1.1 christos current_int_val.val);
2025 1.1 christos lex ();
2026 1.1 christos break;
2027 1.1 christos
2028 1.1 christos case FLOAT:
2029 1.1 christos result = make_operation<float_const_operation> (current_float_val.type,
2030 1.1 christos current_float_val.val);
2031 1.1 christos lex ();
2032 1.1 christos break;
2033 1.1 christos
2034 1.1 christos case STRING:
2035 1.1 christos result = parse_string ();
2036 1.1 christos lex ();
2037 1.1 christos break;
2038 1.1 christos
2039 1.1 christos case BYTESTRING:
2040 1.1 christos result = make_operation<string_operation> (get_string ());
2041 1.1 christos lex ();
2042 1.1 christos break;
2043 1.1 christos
2044 1.1 christos case KW_TRUE:
2045 1.1 christos case KW_FALSE:
2046 1.1 christos result = make_operation<bool_operation> (current_token == KW_TRUE);
2047 1.1 christos lex ();
2048 1.1 christos break;
2049 1.1 christos
2050 1.1 christos case GDBVAR:
2051 1.1 christos /* This is kind of a hacky approach. */
2052 1.1 christos {
2053 1.1 christos pstate->push_dollar (current_string_val);
2054 1.1 christos result = pstate->pop ();
2055 1.1 christos lex ();
2056 1.1 christos }
2057 1.1 christos break;
2058 1.1 christos
2059 1.1 christos case KW_SELF:
2060 1.1 christos case KW_SUPER:
2061 1.1 christos case COLONCOLON:
2062 1.1 christos case KW_EXTERN:
2063 1.1 christos case IDENT:
2064 1.1 christos result = parse_path_expr ();
2065 1.1 christos break;
2066 1.1 christos
2067 1.1 christos case '*':
2068 1.1 christos lex ();
2069 1.1 christos result = make_operation<rust_unop_ind_operation> (parse_atom (true));
2070 1.1 christos break;
2071 1.1 christos case '+':
2072 1.1 christos lex ();
2073 1.1 christos result = make_operation<unary_plus_operation> (parse_atom (true));
2074 1.1 christos break;
2075 1.1 christos case '-':
2076 1.1 christos lex ();
2077 1.1 christos result = make_operation<unary_neg_operation> (parse_atom (true));
2078 1.1 christos break;
2079 1.1 christos case '!':
2080 1.1 christos lex ();
2081 1.1 christos result = make_operation<rust_unop_compl_operation> (parse_atom (true));
2082 1.1 christos break;
2083 1.1 christos case KW_SIZEOF:
2084 1.1 christos result = parse_sizeof ();
2085 1.1 christos break;
2086 1.1 christos case '&':
2087 1.1 christos result = parse_addr ();
2088 1.1 christos break;
2089 1.1 christos
2090 1.1 christos default:
2091 1.1 christos if (!required)
2092 1.1 christos return {};
2093 1.1 christos error (_("unexpected token"));
2094 1.1 christos }
2095 1.1 christos
2096 1.1 christos /* Now parse suffixes. */
2097 1.1 christos while (true)
2098 1.1 christos {
2099 1.1 christos switch (current_token)
2100 1.1 christos {
2101 1.1 christos case '.':
2102 1.1 christos result = parse_field (std::move (result));
2103 1.1 christos break;
2104 1.1 christos
2105 1.1 christos case '[':
2106 1.1 christos result = parse_index (std::move (result));
2107 1.1 christos break;
2108 1.1 christos
2109 1.1 christos case '(':
2110 1.1 christos result = parse_call (std::move (result));
2111 1.1 christos break;
2112 1.1 christos
2113 1.1 christos default:
2114 1.1 christos return result;
2115 1.1 christos }
2116 1.1 christos }
2117 1.1 christos }
2118 1.1 christos
2119 1.1 christos
2120 1.1 christos
2122 1.1 christos /* The parser as exposed to gdb. */
2123 1.1 christos
2124 1.1 christos int
2125 1.1 christos rust_language::parser (struct parser_state *state) const
2126 1.1 christos {
2127 1.1 christos rust_parser parser (state);
2128 1.1 christos
2129 1.1 christos operation_up result;
2130 1.1 christos try
2131 1.1 christos {
2132 1.1 christos result = parser.parse_entry_point ();
2133 1.1 christos }
2134 1.1 christos catch (const gdb_exception &exc)
2135 1.1 christos {
2136 1.1 christos if (state->parse_completion)
2137 1.1 christos {
2138 1.1 christos result = std::move (parser.completion_op);
2139 1.1 christos if (result == nullptr)
2140 1.1 christos throw;
2141 1.1 christos }
2142 1.1 christos else
2143 1.1 christos throw;
2144 1.1 christos }
2145 1.1 christos
2146 1.1 christos state->set_operation (std::move (result));
2147 1.1 christos
2148 1.1 christos return 0;
2149 1.1 christos }
2150 1.1 christos
2151 1.1 christos
2152 1.1 christos
2154 1.1 christos #if GDB_SELF_TEST
2155 1.1 christos
2156 1.1 christos /* A test helper that lexes a string, expecting a single token. */
2157 1.1 christos
2158 1.1 christos static void
2159 1.1 christos rust_lex_test_one (rust_parser *parser, const char *input, int expected)
2160 1.1 christos {
2161 1.1 christos int token;
2162 1.1 christos
2163 1.1 christos parser->reset (input);
2164 1.1 christos
2165 1.1 christos token = parser->lex_one_token ();
2166 1.1 christos SELF_CHECK (token == expected);
2167 1.1 christos
2168 1.1 christos if (token)
2169 1.1 christos {
2170 1.1 christos token = parser->lex_one_token ();
2171 1.1 christos SELF_CHECK (token == 0);
2172 1.1 christos }
2173 1.1 christos }
2174 1.1 christos
2175 1.1 christos /* Test that INPUT lexes as the integer VALUE. */
2176 1.1 christos
2177 1.1 christos static void
2178 1.1 christos rust_lex_int_test (rust_parser *parser, const char *input,
2179 1.1 christos ULONGEST value, int kind)
2180 1.1 christos {
2181 1.1 christos rust_lex_test_one (parser, input, kind);
2182 1.1 christos SELF_CHECK (parser->current_int_val.val == value);
2183 1.1 christos }
2184 1.1 christos
2185 1.1 christos /* Test that INPUT throws an exception with text ERR. */
2186 1.1 christos
2187 1.1 christos static void
2188 1.1 christos rust_lex_exception_test (rust_parser *parser, const char *input,
2189 1.1 christos const char *err)
2190 1.1 christos {
2191 1.1 christos try
2192 1.1 christos {
2193 1.1 christos /* The "kind" doesn't matter. */
2194 1.1 christos rust_lex_test_one (parser, input, DECIMAL_INTEGER);
2195 1.1 christos SELF_CHECK (0);
2196 1.1 christos }
2197 1.1 christos catch (const gdb_exception_error &except)
2198 1.1 christos {
2199 1.1 christos SELF_CHECK (strcmp (except.what (), err) == 0);
2200 1.1 christos }
2201 1.1 christos }
2202 1.1 christos
2203 1.1 christos /* Test that INPUT lexes as the identifier, string, or byte-string
2204 1.1 christos VALUE. KIND holds the expected token kind. */
2205 1.1 christos
2206 1.1 christos static void
2207 1.1 christos rust_lex_stringish_test (rust_parser *parser, const char *input,
2208 1.1 christos const char *value, int kind)
2209 1.1 christos {
2210 1.1 christos rust_lex_test_one (parser, input, kind);
2211 1.1 christos SELF_CHECK (parser->get_string () == value);
2212 1.1 christos }
2213 1.1 christos
2214 1.1 christos /* Helper to test that a string parses as a given token sequence. */
2215 1.1 christos
2216 1.1 christos static void
2217 1.1 christos rust_lex_test_sequence (rust_parser *parser, const char *input, int len,
2218 1.1 christos const int expected[])
2219 1.1 christos {
2220 1.1 christos int i;
2221 1.1 christos
2222 1.1 christos parser->reset (input);
2223 1.1 christos
2224 1.1 christos for (i = 0; i < len; ++i)
2225 1.1 christos {
2226 1.1 christos int token = parser->lex_one_token ();
2227 1.1 christos SELF_CHECK (token == expected[i]);
2228 1.1 christos }
2229 1.1 christos }
2230 1.1 christos
2231 1.1 christos /* Tests for an integer-parsing corner case. */
2232 1.1 christos
2233 1.1 christos static void
2234 1.1 christos rust_lex_test_trailing_dot (rust_parser *parser)
2235 1.1 christos {
2236 1.1 christos const int expected1[] = { DECIMAL_INTEGER, '.', IDENT, '(', ')', 0 };
2237 1.1 christos const int expected2[] = { INTEGER, '.', IDENT, '(', ')', 0 };
2238 1.1 christos const int expected3[] = { FLOAT, EQEQ, '(', ')', 0 };
2239 1.1 christos const int expected4[] = { DECIMAL_INTEGER, DOTDOT, DECIMAL_INTEGER, 0 };
2240 1.1 christos
2241 1.1 christos rust_lex_test_sequence (parser, "23.g()", ARRAY_SIZE (expected1), expected1);
2242 1.1 christos rust_lex_test_sequence (parser, "23_0.g()", ARRAY_SIZE (expected2),
2243 1.1 christos expected2);
2244 1.1 christos rust_lex_test_sequence (parser, "23.==()", ARRAY_SIZE (expected3),
2245 1.1 christos expected3);
2246 1.1 christos rust_lex_test_sequence (parser, "23..25", ARRAY_SIZE (expected4), expected4);
2247 1.1 christos }
2248 1.1 christos
2249 1.1 christos /* Tests of completion. */
2250 1.1 christos
2251 1.1 christos static void
2252 1.1 christos rust_lex_test_completion (rust_parser *parser)
2253 1.1 christos {
2254 1.1 christos const int expected[] = { IDENT, '.', COMPLETE, 0 };
2255 1.1 christos
2256 1.1 christos parser->pstate->parse_completion = 1;
2257 1.1 christos
2258 1.1 christos rust_lex_test_sequence (parser, "something.wha", ARRAY_SIZE (expected),
2259 1.1 christos expected);
2260 1.1 christos rust_lex_test_sequence (parser, "something.", ARRAY_SIZE (expected),
2261 1.1 christos expected);
2262 1.1 christos
2263 1.1 christos parser->pstate->parse_completion = 0;
2264 1.1 christos }
2265 1.1 christos
2266 1.1 christos /* Test pushback. */
2267 1.1 christos
2268 1.1 christos static void
2269 1.1 christos rust_lex_test_push_back (rust_parser *parser)
2270 1.1 christos {
2271 1.1 christos int token;
2272 1.1 christos
2273 1.1 christos parser->reset (">>=");
2274 1.1 christos
2275 1.1 christos token = parser->lex_one_token ();
2276 1.1 christos SELF_CHECK (token == COMPOUND_ASSIGN);
2277 1.1 christos SELF_CHECK (parser->current_opcode == BINOP_RSH);
2278 1.1 christos
2279 1.1 christos parser->push_back ('=');
2280 1.1 christos
2281 1.1 christos token = parser->lex_one_token ();
2282 1.1 christos SELF_CHECK (token == '=');
2283 1.1 christos
2284 1.1 christos token = parser->lex_one_token ();
2285 1.1 christos SELF_CHECK (token == 0);
2286 1.1 christos }
2287 1.1 christos
2288 1.1 christos /* Unit test the lexer. */
2289 1.1 christos
2290 1.1 christos static void
2291 1.1 christos rust_lex_tests (void)
2292 1.1 christos {
2293 1.1 christos /* Set up dummy "parser", so that rust_type works. */
2294 1.1 christos struct parser_state ps (language_def (language_rust), target_gdbarch (),
2295 1.1 christos nullptr, 0, 0, nullptr, 0, nullptr, false);
2296 1.1 christos rust_parser parser (&ps);
2297 1.1 christos
2298 1.1 christos rust_lex_test_one (&parser, "", 0);
2299 1.1 christos rust_lex_test_one (&parser, " \t \n \r ", 0);
2300 1.1 christos rust_lex_test_one (&parser, "thread 23", 0);
2301 1.1 christos rust_lex_test_one (&parser, "task 23", 0);
2302 1.1 christos rust_lex_test_one (&parser, "th 104", 0);
2303 1.1 christos rust_lex_test_one (&parser, "ta 97", 0);
2304 1.1 christos
2305 1.1 christos rust_lex_int_test (&parser, "'z'", 'z', INTEGER);
2306 1.1 christos rust_lex_int_test (&parser, "'\\xff'", 0xff, INTEGER);
2307 1.1 christos rust_lex_int_test (&parser, "'\\u{1016f}'", 0x1016f, INTEGER);
2308 1.1 christos rust_lex_int_test (&parser, "b'z'", 'z', INTEGER);
2309 1.1 christos rust_lex_int_test (&parser, "b'\\xfe'", 0xfe, INTEGER);
2310 1.1 christos rust_lex_int_test (&parser, "b'\\xFE'", 0xfe, INTEGER);
2311 1.1 christos rust_lex_int_test (&parser, "b'\\xfE'", 0xfe, INTEGER);
2312 1.1 christos
2313 1.1 christos /* Test all escapes in both modes. */
2314 1.1 christos rust_lex_int_test (&parser, "'\\n'", '\n', INTEGER);
2315 1.1 christos rust_lex_int_test (&parser, "'\\r'", '\r', INTEGER);
2316 1.1 christos rust_lex_int_test (&parser, "'\\t'", '\t', INTEGER);
2317 1.1 christos rust_lex_int_test (&parser, "'\\\\'", '\\', INTEGER);
2318 1.1 christos rust_lex_int_test (&parser, "'\\0'", '\0', INTEGER);
2319 1.1 christos rust_lex_int_test (&parser, "'\\''", '\'', INTEGER);
2320 1.1 christos rust_lex_int_test (&parser, "'\\\"'", '"', INTEGER);
2321 1.1 christos
2322 1.1 christos rust_lex_int_test (&parser, "b'\\n'", '\n', INTEGER);
2323 1.1 christos rust_lex_int_test (&parser, "b'\\r'", '\r', INTEGER);
2324 1.1 christos rust_lex_int_test (&parser, "b'\\t'", '\t', INTEGER);
2325 1.1 christos rust_lex_int_test (&parser, "b'\\\\'", '\\', INTEGER);
2326 1.1 christos rust_lex_int_test (&parser, "b'\\0'", '\0', INTEGER);
2327 1.1 christos rust_lex_int_test (&parser, "b'\\''", '\'', INTEGER);
2328 1.1 christos rust_lex_int_test (&parser, "b'\\\"'", '"', INTEGER);
2329 1.1 christos
2330 1.1 christos rust_lex_exception_test (&parser, "'z", "Unterminated character literal");
2331 1.1 christos rust_lex_exception_test (&parser, "b'\\x0'", "Not enough hex digits seen");
2332 1.1 christos rust_lex_exception_test (&parser, "b'\\u{0}'",
2333 1.1 christos "Unicode escape in byte literal");
2334 1.1 christos rust_lex_exception_test (&parser, "'\\x0'", "Not enough hex digits seen");
2335 1.1 christos rust_lex_exception_test (&parser, "'\\u0'", "Missing '{' in Unicode escape");
2336 1.1 christos rust_lex_exception_test (&parser, "'\\u{0", "Missing '}' in Unicode escape");
2337 1.1 christos rust_lex_exception_test (&parser, "'\\u{0000007}", "Overlong hex escape");
2338 1.1 christos rust_lex_exception_test (&parser, "'\\u{}", "Not enough hex digits seen");
2339 1.1 christos rust_lex_exception_test (&parser, "'\\Q'", "Invalid escape \\Q in literal");
2340 1.1 christos rust_lex_exception_test (&parser, "b'\\Q'", "Invalid escape \\Q in literal");
2341 1.1 christos
2342 1.1 christos rust_lex_int_test (&parser, "23", 23, DECIMAL_INTEGER);
2343 1.1 christos rust_lex_int_test (&parser, "2_344__29", 234429, INTEGER);
2344 1.1 christos rust_lex_int_test (&parser, "0x1f", 0x1f, INTEGER);
2345 1.1 christos rust_lex_int_test (&parser, "23usize", 23, INTEGER);
2346 1.1 christos rust_lex_int_test (&parser, "23i32", 23, INTEGER);
2347 1.1 christos rust_lex_int_test (&parser, "0x1_f", 0x1f, INTEGER);
2348 1.1 christos rust_lex_int_test (&parser, "0b1_101011__", 0x6b, INTEGER);
2349 1.1 christos rust_lex_int_test (&parser, "0o001177i64", 639, INTEGER);
2350 1.1 christos rust_lex_int_test (&parser, "0x123456789u64", 0x123456789ull, INTEGER);
2351 1.1 christos
2352 1.1 christos rust_lex_test_trailing_dot (&parser);
2353 1.1 christos
2354 1.1 christos rust_lex_test_one (&parser, "23.", FLOAT);
2355 1.1 christos rust_lex_test_one (&parser, "23.99f32", FLOAT);
2356 1.1 christos rust_lex_test_one (&parser, "23e7", FLOAT);
2357 1.1 christos rust_lex_test_one (&parser, "23E-7", FLOAT);
2358 1.1 christos rust_lex_test_one (&parser, "23e+7", FLOAT);
2359 1.1 christos rust_lex_test_one (&parser, "23.99e+7f64", FLOAT);
2360 1.1 christos rust_lex_test_one (&parser, "23.82f32", FLOAT);
2361 1.1 christos
2362 1.1 christos rust_lex_stringish_test (&parser, "hibob", "hibob", IDENT);
2363 1.1 christos rust_lex_stringish_test (&parser, "hibob__93", "hibob__93", IDENT);
2364 1.1 christos rust_lex_stringish_test (&parser, "thread", "thread", IDENT);
2365 1.1 christos rust_lex_stringish_test (&parser, "r#true", "true", IDENT);
2366 1.1 christos
2367 1.1 christos const int expected1[] = { IDENT, DECIMAL_INTEGER, 0 };
2368 1.1 christos rust_lex_test_sequence (&parser, "r#thread 23", ARRAY_SIZE (expected1),
2369 1.1 christos expected1);
2370 1.1 christos const int expected2[] = { IDENT, '#', 0 };
2371 1.1 christos rust_lex_test_sequence (&parser, "r#", ARRAY_SIZE (expected2), expected2);
2372 1.1 christos
2373 1.1 christos rust_lex_stringish_test (&parser, "\"string\"", "string", STRING);
2374 1.1 christos rust_lex_stringish_test (&parser, "\"str\\ting\"", "str\ting", STRING);
2375 1.1 christos rust_lex_stringish_test (&parser, "\"str\\\"ing\"", "str\"ing", STRING);
2376 1.1 christos rust_lex_stringish_test (&parser, "r\"str\\ing\"", "str\\ing", STRING);
2377 1.1 christos rust_lex_stringish_test (&parser, "r#\"str\\ting\"#", "str\\ting", STRING);
2378 1.1 christos rust_lex_stringish_test (&parser, "r###\"str\\\"ing\"###", "str\\\"ing",
2379 1.1 christos STRING);
2380 1.1 christos
2381 1.1 christos rust_lex_stringish_test (&parser, "b\"string\"", "string", BYTESTRING);
2382 1.1 christos rust_lex_stringish_test (&parser, "b\"\x73tring\"", "string", BYTESTRING);
2383 1.1 christos rust_lex_stringish_test (&parser, "b\"str\\\"ing\"", "str\"ing", BYTESTRING);
2384 1.1 christos rust_lex_stringish_test (&parser, "br####\"\\x73tring\"####", "\\x73tring",
2385 1.1 christos BYTESTRING);
2386 1.1 christos
2387 1.1 christos for (const auto &candidate : identifier_tokens)
2388 1.1 christos rust_lex_test_one (&parser, candidate.name, candidate.value);
2389 1.1 christos
2390 1.1 christos for (const auto &candidate : operator_tokens)
2391 1.1 christos rust_lex_test_one (&parser, candidate.name, candidate.value);
2392 1.1 christos
2393 1.1 christos rust_lex_test_completion (&parser);
2394 1.1 christos rust_lex_test_push_back (&parser);
2395 1.1 christos }
2396 1.1 christos
2397 1.1 christos #endif /* GDB_SELF_TEST */
2398 1.1 christos
2399 1.1 christos
2400 1.1 christos
2402 1.1 christos void _initialize_rust_exp ();
2403 1.1 christos void
2404 1.1 christos _initialize_rust_exp ()
2405 1.1 christos {
2406 1.1 christos int code = regcomp (&number_regex, number_regex_text, REG_EXTENDED);
2407 1.1 christos /* If the regular expression was incorrect, it was a programming
2408 1.1 christos error. */
2409 1.1 christos gdb_assert (code == 0);
2410 1.1 christos
2411 #if GDB_SELF_TEST
2412 selftests::register_test ("rust-lex", rust_lex_tests);
2413 #endif
2414 }
2415