Line data Source code
1 : // Copyright (C) 2025-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : /* DO NOT INCLUDE ANYWHERE - this is automatically included
20 : * by rust-parse-impl.h
21 : * This is also the reason why there are no include guards. */
22 :
23 : #include "rust-parse.h"
24 :
25 : namespace Rust {
26 :
27 : // Parses a block expression, including the curly braces at start and end.
28 : template <typename ManagedTokenSource>
29 : tl::expected<std::unique_ptr<AST::BlockExpr>, Parse::Error::Node>
30 41762 : Parser<ManagedTokenSource>::parse_block_expr (
31 : AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label,
32 : location_t pratt_parsed_loc)
33 : {
34 41762 : location_t locus = pratt_parsed_loc;
35 41762 : if (locus == UNKNOWN_LOCATION)
36 : {
37 39117 : locus = lexer.peek_token ()->get_locus ();
38 39117 : if (!skip_token (LEFT_CURLY))
39 : {
40 0 : skip_after_end_block ();
41 : return tl::unexpected<Parse::Error::Node> (
42 0 : Parse::Error::Node::MALFORMED);
43 : }
44 : }
45 :
46 41762 : AST::AttrVec inner_attrs = parse_inner_attributes ();
47 :
48 : // parse statements and expression
49 41762 : std::vector<std::unique_ptr<AST::Stmt>> stmts;
50 41762 : std::unique_ptr<AST::Expr> expr = nullptr;
51 :
52 41762 : const_TokenPtr t = lexer.peek_token ();
53 115174 : while (t->get_id () != RIGHT_CURLY)
54 : {
55 73412 : auto expr_or_stmt = parse_stmt_or_expr ();
56 73412 : if (!expr_or_stmt)
57 : {
58 35 : skip_after_end_block ();
59 : return tl::unexpected<Parse::Error::Node> (
60 35 : Parse::Error::Node::CHILD_ERROR);
61 : }
62 :
63 73377 : t = lexer.peek_token ();
64 :
65 73377 : if (expr_or_stmt->stmt != nullptr)
66 : {
67 42468 : stmts.push_back (std::move (expr_or_stmt->stmt));
68 : }
69 : else
70 : {
71 : // assign to expression and end parsing inside
72 30909 : expr = std::move (expr_or_stmt->expr);
73 : }
74 : }
75 :
76 41727 : location_t end_locus = t->get_locus ();
77 :
78 41727 : if (!skip_token (RIGHT_CURLY))
79 : {
80 : // We don't need to throw an error as it already reported by skip_token
81 0 : skip_after_end_block ();
82 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
83 : }
84 :
85 : // grammar allows for empty block expressions
86 :
87 41727 : stmts.shrink_to_fit ();
88 :
89 41727 : return std::unique_ptr<AST::BlockExpr> (
90 41730 : new AST::BlockExpr (std::move (stmts), std::move (expr),
91 : std::move (inner_attrs), std::move (outer_attrs),
92 41727 : std::move (label), locus, end_locus));
93 41762 : }
94 :
95 : /* Parse an anonymous const expression. This can be a regular const expression
96 : * or an underscore for deferred const inference */
97 : template <typename ManagedTokenSource>
98 : tl::expected<AST::AnonConst, Parse::Error::Node>
99 1020 : Parser<ManagedTokenSource>::parse_anon_const ()
100 : {
101 1020 : auto current = lexer.peek_token ();
102 1020 : auto locus = current->get_locus ();
103 :
104 : // Special case deferred inference constants
105 1020 : if (maybe_skip_token (UNDERSCORE))
106 13 : return AST::AnonConst (locus);
107 :
108 1007 : auto expr = parse_expr ();
109 :
110 1007 : if (!expr)
111 1 : return tl::make_unexpected (Parse::Error::Node{});
112 :
113 2012 : return AST::AnonConst (std::move (expr.value ()), locus);
114 1007 : }
115 :
116 : /* Parse a "const block", a block preceded by the `const` keyword whose
117 : * statements can be const evaluated and used in constant contexts */
118 : template <typename ManagedTokenSource>
119 : tl::expected<std::unique_ptr<AST::ConstBlock>, Parse::Error::Node>
120 15 : Parser<ManagedTokenSource>::parse_const_block_expr (AST::AttrVec outer_attrs,
121 : location_t locus)
122 : {
123 15 : auto block_res = parse_block_expr ();
124 :
125 15 : if (!block_res)
126 : {
127 0 : add_error (Error (locus, "failed to parse inner block in const block"));
128 0 : skip_after_end_block ();
129 :
130 : return tl::unexpected<Parse::Error::Node> (
131 0 : Parse::Error::Node::CHILD_ERROR);
132 : }
133 15 : auto block = std::move (block_res.value ());
134 :
135 15 : auto block_locus = block->get_locus ();
136 :
137 30 : return std::make_unique<AST::ConstBlock> (AST::AnonConst (std::move (block),
138 : block_locus),
139 15 : locus, std::move (outer_attrs));
140 15 : }
141 :
142 : /* Parses a "grouped" expression (expression in parentheses), used to control
143 : * precedence. */
144 : template <typename ManagedTokenSource>
145 : tl::expected<std::unique_ptr<AST::GroupedExpr>, Parse::Error::Node>
146 0 : Parser<ManagedTokenSource>::parse_grouped_expr (AST::AttrVec outer_attrs)
147 : {
148 0 : location_t locus = lexer.peek_token ()->get_locus ();
149 0 : skip_token (LEFT_PAREN);
150 :
151 0 : AST::AttrVec inner_attrs = parse_inner_attributes ();
152 :
153 : // parse required expr inside parentheses
154 0 : auto expr_in_parens = parse_expr ();
155 0 : if (!expr_in_parens)
156 : {
157 : // skip after somewhere?
158 : // error?
159 : return tl::unexpected<Parse::Error::Node> (
160 0 : Parse::Error::Node::CHILD_ERROR);
161 : }
162 :
163 0 : if (!skip_token (RIGHT_PAREN))
164 : {
165 : // skip after somewhere?
166 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
167 : }
168 :
169 0 : return std::unique_ptr<AST::GroupedExpr> (
170 0 : new AST::GroupedExpr (std::move (expr_in_parens.value ()),
171 : std::move (inner_attrs), std::move (outer_attrs),
172 0 : locus));
173 0 : }
174 :
175 : // Parses a closure expression (closure definition).
176 : template <typename ManagedTokenSource>
177 : tl::expected<std::unique_ptr<AST::ClosureExpr>, Parse::Error::Node>
178 0 : Parser<ManagedTokenSource>::parse_closure_expr (AST::AttrVec outer_attrs)
179 : {
180 0 : location_t locus = lexer.peek_token ()->get_locus ();
181 : // detect optional "move"
182 0 : bool has_move = false;
183 0 : if (lexer.peek_token ()->get_id () == MOVE)
184 : {
185 0 : lexer.skip_token ();
186 0 : has_move = true;
187 : }
188 :
189 : // handle parameter list
190 0 : std::vector<AST::ClosureParam> params;
191 :
192 0 : const_TokenPtr t = lexer.peek_token ();
193 0 : switch (t->get_id ())
194 : {
195 0 : case OR:
196 : // skip token, no parameters
197 0 : lexer.skip_token ();
198 : break;
199 0 : case PIPE:
200 : // actually may have parameters
201 0 : lexer.skip_token ();
202 0 : t = lexer.peek_token ();
203 :
204 0 : while (t->get_id () != PIPE)
205 : {
206 0 : AST::ClosureParam param = parse_closure_param ();
207 0 : if (param.is_error ())
208 : {
209 : // TODO is this really an error?
210 0 : Error error (t->get_locus (), "could not parse closure param");
211 0 : add_error (std::move (error));
212 :
213 : break;
214 0 : }
215 0 : params.push_back (std::move (param));
216 :
217 0 : if (lexer.peek_token ()->get_id () != COMMA)
218 : {
219 0 : lexer.skip_token ();
220 : // not an error but means param list is done
221 : break;
222 : }
223 : // skip comma
224 0 : lexer.skip_token ();
225 :
226 0 : t = lexer.peek_token ();
227 : }
228 0 : params.shrink_to_fit ();
229 : break;
230 0 : default:
231 0 : add_error (Error (t->get_locus (),
232 : "unexpected token %qs in closure expression - expected "
233 : "%<|%> or %<||%>",
234 : t->get_token_description ()));
235 :
236 : // skip somewhere?
237 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
238 : }
239 :
240 : // again branch based on next token
241 0 : t = lexer.peek_token ();
242 0 : if (t->get_id () == RETURN_TYPE)
243 : {
244 : // must be return type closure with block expr
245 :
246 : // skip "return type" token
247 0 : lexer.skip_token ();
248 :
249 : // parse actual type, which is required
250 0 : std::unique_ptr<AST::TypeNoBounds> type = parse_type_no_bounds ();
251 0 : if (type == nullptr)
252 : {
253 : // error
254 0 : Error error (t->get_locus (), "failed to parse type for closure");
255 0 : add_error (std::move (error));
256 :
257 : // skip somewhere?
258 : return tl::unexpected<Parse::Error::Node> (
259 0 : Parse::Error::Node::CHILD_ERROR);
260 0 : }
261 :
262 : // parse block expr, which is required
263 0 : auto block = parse_block_expr ();
264 0 : if (!block)
265 : {
266 : // error
267 0 : Error error (lexer.peek_token ()->get_locus (),
268 : "failed to parse block expr in closure");
269 0 : add_error (std::move (error));
270 :
271 : // skip somewhere?
272 : return tl::unexpected<Parse::Error::Node> (
273 0 : Parse::Error::Node::CHILD_ERROR);
274 0 : }
275 :
276 0 : return std::unique_ptr<AST::ClosureExprInnerTyped> (
277 0 : new AST::ClosureExprInnerTyped (std::move (type),
278 0 : std::move (block.value ()),
279 : std::move (params), locus, has_move,
280 0 : std::move (outer_attrs)));
281 0 : }
282 : else
283 : {
284 : // must be expr-only closure
285 :
286 : // parse expr, which is required
287 0 : auto expr = parse_expr ();
288 0 : if (!expr)
289 : {
290 0 : Error error (t->get_locus (),
291 : "failed to parse expression in closure");
292 0 : add_error (std::move (error));
293 :
294 : // skip somewhere?
295 : return tl::unexpected<Parse::Error::Node> (
296 0 : Parse::Error::Node::CHILD_ERROR);
297 0 : }
298 :
299 0 : return std::unique_ptr<AST::ClosureExprInner> (
300 0 : new AST::ClosureExprInner (std::move (expr.value ()),
301 : std::move (params), locus, has_move,
302 0 : std::move (outer_attrs)));
303 0 : }
304 0 : }
305 :
306 : // Parses a literal token (to literal expression).
307 : template <typename ManagedTokenSource>
308 : tl::expected<std::unique_ptr<AST::LiteralExpr>, Parse::Error::Node>
309 3981 : Parser<ManagedTokenSource>::parse_literal_expr (AST::AttrVec outer_attrs)
310 : {
311 : // TODO: change if literal representation in lexer changes
312 :
313 3981 : std::string literal_value;
314 3981 : AST::Literal::LitType type = AST::Literal::STRING;
315 :
316 : // branch based on token
317 3981 : const_TokenPtr t = lexer.peek_token ();
318 3981 : switch (t->get_id ())
319 : {
320 2 : case CHAR_LITERAL:
321 2 : type = AST::Literal::CHAR;
322 2 : literal_value = t->get_str ();
323 2 : lexer.skip_token ();
324 : break;
325 574 : case STRING_LITERAL:
326 574 : type = AST::Literal::STRING;
327 574 : literal_value = t->get_str ();
328 574 : lexer.skip_token ();
329 : break;
330 0 : case BYTE_CHAR_LITERAL:
331 0 : type = AST::Literal::BYTE;
332 0 : literal_value = t->get_str ();
333 0 : lexer.skip_token ();
334 : break;
335 1 : case BYTE_STRING_LITERAL:
336 1 : type = AST::Literal::BYTE_STRING;
337 1 : literal_value = t->get_str ();
338 1 : lexer.skip_token ();
339 : break;
340 26 : case RAW_STRING_LITERAL:
341 26 : type = AST::Literal::RAW_STRING;
342 26 : literal_value = t->get_str ();
343 26 : lexer.skip_token ();
344 : break;
345 0 : case C_STRING_LITERAL:
346 : {
347 0 : if (flag_c_style_string_literals)
348 : {
349 0 : type = AST::Literal::C_STRING;
350 0 : literal_value = t->get_str ();
351 0 : lexer.skip_token ();
352 : }
353 : else
354 : {
355 0 : add_error (
356 0 : Error (t->get_locus (),
357 : "unexpected token %qs when parsing literal expression - "
358 : "C-style string literals require "
359 : "%<-frust-c-style-string-literals%> to be enabled",
360 : t->get_token_description ()));
361 : return tl::unexpected<Parse::Error::Node> (
362 0 : Parse::Error::Node::MALFORMED);
363 : }
364 : }
365 :
366 : break;
367 3369 : case INT_LITERAL:
368 3369 : type = AST::Literal::INT;
369 3369 : literal_value = LiteralResolve::evaluate_integer_literal (t);
370 3369 : lexer.skip_token ();
371 : break;
372 1 : case FLOAT_LITERAL:
373 1 : type = AST::Literal::FLOAT;
374 1 : literal_value = LiteralResolve::evaluate_float_literal (t);
375 1 : lexer.skip_token ();
376 : break;
377 : // case BOOL_LITERAL
378 : // use true and false keywords rather than "bool literal" Rust terminology
379 0 : case TRUE_LITERAL:
380 0 : type = AST::Literal::BOOL;
381 0 : literal_value = Values::Keywords::TRUE_LITERAL;
382 0 : lexer.skip_token ();
383 : break;
384 1 : case FALSE_LITERAL:
385 1 : type = AST::Literal::BOOL;
386 1 : literal_value = Values::Keywords::FALSE_LITERAL;
387 1 : lexer.skip_token ();
388 : break;
389 7 : default:
390 : // error - cannot be a literal expr
391 7 : add_error (Error (t->get_locus (),
392 : "unexpected token %qs when parsing literal expression",
393 : t->get_token_description ()));
394 :
395 : // skip?
396 7 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
397 : }
398 :
399 3974 : auto type_hint
400 3974 : = (t->get_id () == INT_LITERAL || t->get_id () == FLOAT_LITERAL)
401 10714 : ? LiteralResolve::resolve_literal_suffix (t)
402 604 : : t->get_type_hint ();
403 :
404 : // create literal based on stuff in switch
405 3974 : return std::unique_ptr<AST::LiteralExpr> (
406 7948 : new AST::LiteralExpr (std::move (literal_value), std::move (type),
407 3974 : type_hint, std::move (outer_attrs), t->get_locus ()));
408 3981 : }
409 :
410 : template <typename ManagedTokenSource>
411 : tl::expected<std::unique_ptr<AST::BoxExpr>, Parse::Error::Node>
412 5 : Parser<ManagedTokenSource>::parse_box_expr (AST::AttrVec outer_attrs,
413 : location_t pratt_parsed_loc)
414 : {
415 5 : location_t locus = pratt_parsed_loc;
416 5 : if (locus == UNKNOWN_LOCATION)
417 : {
418 0 : locus = lexer.peek_token ()->get_locus ();
419 0 : skip_token (BOX);
420 : }
421 :
422 5 : ParseRestrictions restrictions;
423 : restrictions.expr_can_be_null = false;
424 :
425 5 : auto expr = parse_expr (AST::AttrVec (), restrictions);
426 5 : if (!expr)
427 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
428 :
429 5 : return std::unique_ptr<AST::BoxExpr> (
430 5 : new AST::BoxExpr (std::move (expr.value ()), std::move (outer_attrs),
431 5 : locus));
432 5 : }
433 :
434 : // Parses a return expression (including any expression to return).
435 : template <typename ManagedTokenSource>
436 : tl::expected<std::unique_ptr<AST::ReturnExpr>, Parse::Error::Node>
437 932 : Parser<ManagedTokenSource>::parse_return_expr (AST::AttrVec outer_attrs,
438 : location_t pratt_parsed_loc)
439 : {
440 932 : location_t locus = pratt_parsed_loc;
441 932 : if (locus == UNKNOWN_LOCATION)
442 : {
443 0 : locus = lexer.peek_token ()->get_locus ();
444 0 : skip_token (RETURN_KW);
445 : }
446 :
447 : // parse expression to return, if it exists
448 932 : ParseRestrictions restrictions;
449 932 : restrictions.expr_can_be_null = true;
450 932 : auto returned_expr = parse_expr (AST::AttrVec (), restrictions);
451 932 : tl::optional<std::unique_ptr<AST::Expr>> expr = tl::nullopt;
452 932 : if (returned_expr)
453 884 : expr = std::move (returned_expr.value ());
454 :
455 932 : return std::make_unique<AST::ReturnExpr> (std::move (expr),
456 932 : std::move (outer_attrs), locus);
457 932 : }
458 :
459 : // Parses a try expression.
460 : template <typename ManagedTokenSource>
461 : tl::expected<std::unique_ptr<AST::TryExpr>, Parse::Error::Node>
462 31 : Parser<ManagedTokenSource>::parse_try_expr (AST::AttrVec outer_attrs,
463 : location_t pratt_parsed_loc)
464 : {
465 31 : location_t locus = pratt_parsed_loc;
466 31 : if (locus == UNKNOWN_LOCATION)
467 : {
468 0 : locus = lexer.peek_token ()->get_locus ();
469 0 : skip_token (TRY);
470 : }
471 :
472 31 : auto block_expr = parse_block_expr ();
473 :
474 31 : if (!block_expr)
475 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
476 :
477 31 : return std::unique_ptr<AST::TryExpr> (
478 31 : new AST::TryExpr (std::move (block_expr.value ()), std::move (outer_attrs),
479 31 : locus));
480 31 : }
481 :
482 : /* Parses a break expression (including any label to break to AND any return
483 : * expression). */
484 : template <typename ManagedTokenSource>
485 : tl::expected<std::unique_ptr<AST::BreakExpr>, Parse::Error::Node>
486 127 : Parser<ManagedTokenSource>::parse_break_expr (AST::AttrVec outer_attrs,
487 : location_t pratt_parsed_loc)
488 : {
489 127 : location_t locus = pratt_parsed_loc;
490 127 : if (locus == UNKNOWN_LOCATION)
491 : {
492 0 : locus = lexer.peek_token ()->get_locus ();
493 0 : skip_token (BREAK);
494 : }
495 :
496 127 : auto parsed_label = parse_lifetime (false);
497 127 : auto label = (parsed_label)
498 127 : ? tl::optional<AST::Lifetime> (parsed_label.value ())
499 : : tl::nullopt;
500 :
501 : // parse break return expression if it exists
502 127 : ParseRestrictions restrictions;
503 127 : restrictions.expr_can_be_null = true;
504 127 : auto return_expr = parse_expr (AST::AttrVec (), restrictions);
505 :
506 127 : if (return_expr)
507 26 : return std::unique_ptr<AST::BreakExpr> (
508 78 : new AST::BreakExpr (std::move (label), std::move (return_expr.value ()),
509 26 : std::move (outer_attrs), locus));
510 101 : else if (return_expr.error () == Parse::Error::Expr::NULL_EXPR)
511 101 : return std::unique_ptr<AST::BreakExpr> (
512 202 : new AST::BreakExpr (std::move (label), tl::nullopt,
513 101 : std::move (outer_attrs), locus));
514 : else
515 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
516 164 : }
517 :
518 : // Parses a continue expression (including any label to continue from).
519 : template <typename ManagedTokenSource>
520 : std::unique_ptr<AST::ContinueExpr>
521 40 : Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs,
522 : location_t pratt_parsed_loc)
523 : {
524 40 : location_t locus = pratt_parsed_loc;
525 40 : if (locus == UNKNOWN_LOCATION)
526 : {
527 0 : locus = lexer.peek_token ()->get_locus ();
528 0 : skip_token (CONTINUE);
529 : }
530 :
531 40 : auto parsed_label = parse_lifetime (false);
532 40 : auto label = (parsed_label)
533 40 : ? tl::optional<AST::Lifetime> (parsed_label.value ())
534 : : tl::nullopt;
535 :
536 : return std::make_unique<AST::ContinueExpr> (std::move (label),
537 40 : std::move (outer_attrs), locus);
538 40 : }
539 :
540 : /* Parses an if expression of any kind, including with else, else if, else if
541 : * let, and neither. Note that any outer attributes will be ignored because if
542 : * expressions don't support them. */
543 : template <typename ManagedTokenSource>
544 : tl::expected<std::unique_ptr<AST::IfExpr>, Parse::Error::Node>
545 4292 : Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
546 : location_t pratt_parsed_loc)
547 : {
548 : // TODO: make having outer attributes an error?
549 4292 : location_t locus = pratt_parsed_loc;
550 4292 : if (locus == UNKNOWN_LOCATION)
551 : {
552 434 : locus = lexer.peek_token ()->get_locus ();
553 434 : if (!skip_token (IF))
554 : {
555 0 : skip_after_end_block ();
556 : return tl::unexpected<Parse::Error::Node> (
557 0 : Parse::Error::Node::MALFORMED);
558 : }
559 : }
560 :
561 : // detect accidental if let
562 8584 : if (lexer.peek_token ()->get_id () == LET)
563 : {
564 0 : Error error (lexer.peek_token ()->get_locus (),
565 : "if let expression probably exists, but is being parsed "
566 : "as an if expression. This may be a parser error");
567 0 : add_error (std::move (error));
568 :
569 : // skip somewhere?
570 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
571 0 : }
572 :
573 : /* parse required condition expr - HACK to prevent struct expr from being
574 : * parsed */
575 4292 : ParseRestrictions no_struct_expr;
576 4292 : no_struct_expr.can_be_struct_expr = false;
577 4292 : auto condition = parse_expr ({}, no_struct_expr);
578 4292 : if (!condition)
579 : {
580 0 : Error error (lexer.peek_token ()->get_locus (),
581 : "failed to parse condition expression in if expression");
582 0 : add_error (std::move (error));
583 :
584 : // skip somewhere?
585 : return tl::unexpected<Parse::Error::Node> (
586 0 : Parse::Error::Node::CHILD_ERROR);
587 0 : }
588 :
589 : // parse required block expr
590 4292 : auto if_body = parse_block_expr ();
591 4292 : if (!if_body)
592 1 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
593 :
594 : // branch to parse end or else (and then else, else if, or else if let)
595 8582 : if (lexer.peek_token ()->get_id () != ELSE)
596 : {
597 : // single selection - end of if expression
598 1916 : return std::unique_ptr<AST::IfExpr> (
599 1916 : new AST::IfExpr (std::move (condition.value ()),
600 1916 : std::move (if_body.value ()), std::move (outer_attrs),
601 1916 : locus));
602 : }
603 : else
604 : {
605 : // double or multiple selection - branch on end, else if, or else if let
606 :
607 : // skip "else"
608 2375 : lexer.skip_token ();
609 :
610 : // branch on whether next token is '{' or 'if'
611 2375 : const_TokenPtr t = lexer.peek_token ();
612 2375 : switch (t->get_id ())
613 : {
614 1941 : case LEFT_CURLY:
615 : {
616 : // double selection - else
617 : // parse else block expr (required)
618 1941 : auto else_body = parse_block_expr ();
619 1941 : if (!else_body)
620 : {
621 0 : Error error (lexer.peek_token ()->get_locus (),
622 : "failed to parse else body block expression in "
623 : "if expression");
624 0 : add_error (std::move (error));
625 :
626 : // skip somewhere?
627 : return tl::unexpected<Parse::Error::Node> (
628 0 : Parse::Error::Node::CHILD_ERROR);
629 0 : }
630 :
631 1941 : return std::unique_ptr<AST::IfExprConseqElse> (
632 3882 : new AST::IfExprConseqElse (std::move (condition.value ()),
633 1941 : std::move (if_body.value ()),
634 1941 : std::move (else_body.value ()),
635 1941 : std::move (outer_attrs), locus));
636 1941 : }
637 434 : case IF:
638 : {
639 : // multiple selection - else if or else if let
640 : // branch on whether next token is 'let' or not
641 868 : if (lexer.peek_token (1)->get_id () == LET)
642 : {
643 : // parse if let expr (required)
644 1 : auto if_let_expr = parse_if_let_expr ();
645 1 : if (!if_let_expr)
646 : {
647 0 : Error error (lexer.peek_token ()->get_locus (),
648 : "failed to parse (else) if let expression "
649 : "after if expression");
650 0 : add_error (std::move (error));
651 :
652 : // skip somewhere?
653 : return tl::unexpected<Parse::Error::Node> (
654 0 : Parse::Error::Node::CHILD_ERROR);
655 0 : }
656 :
657 1 : return std::unique_ptr<AST::IfExprConseqElse> (
658 2 : new AST::IfExprConseqElse (std::move (condition.value ()),
659 1 : std::move (if_body.value ()),
660 1 : std::move (if_let_expr.value ()),
661 1 : std::move (outer_attrs), locus));
662 1 : }
663 : else
664 : {
665 : // parse if expr (required)
666 433 : auto if_expr = parse_if_expr ();
667 433 : if (!if_expr)
668 : {
669 0 : Error error (lexer.peek_token ()->get_locus (),
670 : "failed to parse (else) if expression after "
671 : "if expression");
672 0 : add_error (std::move (error));
673 :
674 : // skip somewhere?
675 : return tl::unexpected<Parse::Error::Node> (
676 0 : Parse::Error::Node::CHILD_ERROR);
677 0 : }
678 :
679 433 : return std::unique_ptr<AST::IfExprConseqElse> (
680 866 : new AST::IfExprConseqElse (std::move (condition.value ()),
681 433 : std::move (if_body.value ()),
682 433 : std::move (if_expr.value ()),
683 433 : std::move (outer_attrs), locus));
684 433 : }
685 : }
686 0 : default:
687 : // error - invalid token
688 0 : add_error (Error (t->get_locus (),
689 : "unexpected token %qs after else in if expression",
690 : t->get_token_description ()));
691 :
692 : // skip somewhere?
693 : return tl::unexpected<Parse::Error::Node> (
694 0 : Parse::Error::Node::MALFORMED);
695 : }
696 2375 : }
697 8584 : }
698 :
699 : /* Parses an if let expression of any kind, including with else, else if, else
700 : * if let, and none. Note that any outer attributes will be ignored as if let
701 : * expressions don't support them. */
702 : template <typename ManagedTokenSource>
703 : tl::expected<std::unique_ptr<AST::IfLetExpr>, Parse::Error::Node>
704 122 : Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
705 : location_t pratt_parsed_loc)
706 : {
707 : // TODO: make having outer attributes an error?
708 122 : location_t locus = pratt_parsed_loc;
709 122 : if (locus == UNKNOWN_LOCATION)
710 : {
711 2 : locus = lexer.peek_token ()->get_locus ();
712 2 : if (!skip_token (IF))
713 : {
714 0 : skip_after_end_block ();
715 : return tl::unexpected<Parse::Error::Node> (
716 0 : Parse::Error::Node::MALFORMED);
717 : }
718 : }
719 :
720 : // detect accidental if expr parsed as if let expr
721 244 : if (lexer.peek_token ()->get_id () != LET)
722 : {
723 0 : Error error (lexer.peek_token ()->get_locus (),
724 : "if expression probably exists, but is being parsed as an "
725 : "if let expression. This may be a parser error");
726 0 : add_error (std::move (error));
727 :
728 : // skip somewhere?
729 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
730 0 : }
731 122 : lexer.skip_token ();
732 :
733 : // parse match arm patterns (which are required)
734 122 : std::unique_ptr<AST::Pattern> match_arm_pattern
735 : = parse_match_arm_pattern (EQUAL);
736 122 : if (match_arm_pattern == nullptr)
737 : {
738 0 : Error error (
739 0 : lexer.peek_token ()->get_locus (),
740 : "failed to parse any match arm patterns in if let expression");
741 0 : add_error (std::move (error));
742 :
743 : // skip somewhere?
744 : return tl::unexpected<Parse::Error::Node> (
745 0 : Parse::Error::Node::CHILD_ERROR);
746 0 : }
747 :
748 122 : if (!skip_token (EQUAL))
749 : {
750 : // skip somewhere?
751 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
752 : }
753 :
754 : // parse expression (required) - HACK to prevent struct expr being parsed
755 122 : ParseRestrictions no_struct_expr;
756 122 : no_struct_expr.can_be_struct_expr = false;
757 122 : auto scrutinee_expr = parse_expr ({}, no_struct_expr);
758 122 : if (!scrutinee_expr)
759 : {
760 0 : Error error (lexer.peek_token ()->get_locus (),
761 : "failed to parse scrutinee expression in if let expression");
762 0 : add_error (std::move (error));
763 :
764 : // skip somewhere?
765 : return tl::unexpected<Parse::Error::Node> (
766 0 : Parse::Error::Node::CHILD_ERROR);
767 0 : }
768 : /* TODO: check for expression not being a struct expression or lazy boolean
769 : * expression here? or actually probably in semantic analysis. */
770 :
771 : // parse block expression (required)
772 122 : auto if_let_body = parse_block_expr ();
773 122 : if (!if_let_body)
774 : {
775 0 : Error error (
776 0 : lexer.peek_token ()->get_locus (),
777 : "failed to parse if let body block expression in if let expression");
778 0 : add_error (std::move (error));
779 :
780 : // skip somewhere?
781 : return tl::unexpected<Parse::Error::Node> (
782 0 : Parse::Error::Node::CHILD_ERROR);
783 0 : }
784 :
785 : // branch to parse end or else (and then else, else if, or else if let)
786 244 : if (lexer.peek_token ()->get_id () != ELSE)
787 : {
788 : // single selection - end of if let expression
789 160 : return std::unique_ptr<AST::IfLetExpr> (new AST::IfLetExpr (
790 80 : std::move (match_arm_pattern), std::move (scrutinee_expr.value ()),
791 160 : std::move (if_let_body.value ()), std::move (outer_attrs), locus));
792 : }
793 : else
794 : {
795 : // double or multiple selection - branch on end, else if, or else if let
796 :
797 : // skip "else"
798 42 : lexer.skip_token ();
799 :
800 : // branch on whether next token is '{' or 'if'
801 42 : const_TokenPtr t = lexer.peek_token ();
802 42 : switch (t->get_id ())
803 : {
804 40 : case LEFT_CURLY:
805 : {
806 : // double selection - else
807 : // parse else block expr (required)
808 40 : auto else_body = parse_block_expr ();
809 40 : if (!else_body)
810 : {
811 0 : Error error (lexer.peek_token ()->get_locus (),
812 : "failed to parse else body block expression in "
813 : "if let expression");
814 0 : add_error (std::move (error));
815 :
816 : // skip somewhere?
817 : return tl::unexpected<Parse::Error::Node> (
818 0 : Parse::Error::Node::CHILD_ERROR);
819 0 : }
820 :
821 40 : return std::unique_ptr<AST::IfLetExprConseqElse> (
822 80 : new AST::IfLetExprConseqElse (std::move (match_arm_pattern),
823 40 : std::move (scrutinee_expr.value ()),
824 40 : std::move (if_let_body.value ()),
825 40 : std::move (else_body.value ()),
826 40 : std::move (outer_attrs), locus));
827 40 : }
828 2 : case IF:
829 : {
830 : // multiple selection - else if or else if let
831 : // branch on whether next token is 'let' or not
832 4 : if (lexer.peek_token (1)->get_id () == LET)
833 : {
834 : // parse if let expr (required)
835 1 : auto if_let_expr = parse_if_let_expr ();
836 1 : if (!if_let_expr)
837 : {
838 0 : Error error (lexer.peek_token ()->get_locus (),
839 : "failed to parse (else) if let expression "
840 : "after if let expression");
841 0 : add_error (std::move (error));
842 :
843 : // skip somewhere?
844 : return tl::unexpected<Parse::Error::Node> (
845 0 : Parse::Error::Node::CHILD_ERROR);
846 0 : }
847 :
848 1 : return std::unique_ptr<AST::IfLetExprConseqElse> (
849 2 : new AST::IfLetExprConseqElse (
850 : std::move (match_arm_pattern),
851 1 : std::move (scrutinee_expr.value ()),
852 1 : std::move (if_let_body.value ()),
853 1 : std::move (if_let_expr.value ()), std::move (outer_attrs),
854 1 : locus));
855 1 : }
856 : else
857 : {
858 : // parse if expr (required)
859 1 : auto if_expr = parse_if_expr ();
860 1 : if (!if_expr)
861 : {
862 0 : Error error (lexer.peek_token ()->get_locus (),
863 : "failed to parse (else) if expression after "
864 : "if let expression");
865 0 : add_error (std::move (error));
866 :
867 : // skip somewhere?
868 : return tl::unexpected<Parse::Error::Node> (
869 0 : Parse::Error::Node::CHILD_ERROR);
870 0 : }
871 :
872 1 : return std::unique_ptr<AST::IfLetExprConseqElse> (
873 2 : new AST::IfLetExprConseqElse (
874 : std::move (match_arm_pattern),
875 1 : std::move (scrutinee_expr.value ()),
876 1 : std::move (if_let_body.value ()),
877 1 : std::move (if_expr.value ()), std::move (outer_attrs),
878 1 : locus));
879 1 : }
880 : }
881 0 : default:
882 : // error - invalid token
883 0 : add_error (
884 0 : Error (t->get_locus (),
885 : "unexpected token %qs after else in if let expression",
886 : t->get_token_description ()));
887 :
888 : // skip somewhere?
889 : return tl::unexpected<Parse::Error::Node> (
890 0 : Parse::Error::Node::MALFORMED);
891 : }
892 42 : }
893 244 : }
894 :
895 : /* TODO: possibly decide on different method of handling label (i.e. not
896 : * parameter) */
897 :
898 : /* Parses a "loop" infinite loop expression. Label is not parsed and should be
899 : * parsed via parse_labelled_loop_expr, which would call this. */
900 : template <typename ManagedTokenSource>
901 : tl::expected<std::unique_ptr<AST::LoopExpr>, Parse::Error::Node>
902 165 : Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
903 : tl::optional<AST::LoopLabel> label,
904 : location_t pratt_parsed_loc)
905 : {
906 165 : location_t locus = pratt_parsed_loc;
907 165 : if (locus == UNKNOWN_LOCATION)
908 : {
909 49 : if (label)
910 49 : locus = label->get_locus ();
911 : else
912 0 : locus = lexer.peek_token ()->get_locus ();
913 :
914 49 : if (!skip_token (LOOP))
915 : {
916 0 : skip_after_end_block ();
917 : return tl::unexpected<Parse::Error::Node> (
918 0 : Parse::Error::Node::MALFORMED);
919 : }
920 : }
921 : else
922 : {
923 116 : if (label)
924 0 : locus = label->get_locus ();
925 : }
926 :
927 : // parse loop body, which is required
928 165 : auto loop_body = parse_block_expr ();
929 165 : if (!loop_body)
930 1 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
931 :
932 164 : return std::unique_ptr<AST::LoopExpr> (
933 213 : new AST::LoopExpr (std::move (loop_body.value ()), locus, std::move (label),
934 164 : std::move (outer_attrs)));
935 165 : }
936 :
937 : /* Parses a "while" loop expression. Label is not parsed and should be parsed
938 : * via parse_labelled_loop_expr, which would call this. */
939 : template <typename ManagedTokenSource>
940 : tl::expected<std::unique_ptr<AST::WhileLoopExpr>, Parse::Error::Node>
941 187 : Parser<ManagedTokenSource>::parse_while_loop_expr (
942 : AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label,
943 : location_t pratt_parsed_loc)
944 : {
945 187 : location_t locus = pratt_parsed_loc;
946 187 : if (locus == UNKNOWN_LOCATION)
947 : {
948 7 : if (label)
949 7 : locus = label->get_locus ();
950 : else
951 0 : locus = lexer.peek_token ()->get_locus ();
952 :
953 7 : if (!skip_token (WHILE))
954 : {
955 0 : skip_after_end_block ();
956 : return tl::unexpected<Parse::Error::Node> (
957 0 : Parse::Error::Node::MALFORMED);
958 : }
959 : }
960 : else
961 : {
962 180 : if (label)
963 0 : locus = label->get_locus ();
964 : }
965 :
966 : // ensure it isn't a while let loop
967 374 : if (lexer.peek_token ()->get_id () == LET)
968 : {
969 0 : Error error (lexer.peek_token ()->get_locus (),
970 : "appears to be while let loop but is being parsed by "
971 : "while loop - this may be a compiler issue");
972 0 : add_error (std::move (error));
973 :
974 : // skip somewhere?
975 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
976 0 : }
977 :
978 : // parse loop predicate (required) with HACK to prevent struct expr parsing
979 187 : ParseRestrictions no_struct_expr;
980 187 : no_struct_expr.can_be_struct_expr = false;
981 187 : auto predicate = parse_expr ({}, no_struct_expr);
982 187 : if (!predicate)
983 : {
984 0 : Error error (lexer.peek_token ()->get_locus (),
985 : "failed to parse predicate expression in while loop");
986 0 : add_error (std::move (error));
987 :
988 : // skip somewhere?
989 : return tl::unexpected<Parse::Error::Node> (
990 0 : Parse::Error::Node::CHILD_ERROR);
991 0 : }
992 : /* TODO: check that it isn't struct expression here? actually, probably in
993 : * semantic analysis */
994 :
995 : // parse loop body (required)
996 187 : auto body = parse_block_expr ();
997 187 : if (!body)
998 : {
999 0 : Error error (lexer.peek_token ()->get_locus (),
1000 : "failed to parse loop body block expression in while loop");
1001 0 : add_error (std::move (error));
1002 :
1003 : // skip somewhere
1004 : return tl::unexpected<Parse::Error::Node> (
1005 0 : Parse::Error::Node::CHILD_ERROR);
1006 0 : }
1007 :
1008 187 : return std::unique_ptr<AST::WhileLoopExpr> (
1009 381 : new AST::WhileLoopExpr (std::move (predicate.value ()),
1010 187 : std::move (body.value ()), locus, std::move (label),
1011 187 : std::move (outer_attrs)));
1012 374 : }
1013 :
1014 : /* Parses a "while let" loop expression. Label is not parsed and should be
1015 : * parsed via parse_labelled_loop_expr, which would call this. */
1016 : template <typename ManagedTokenSource>
1017 : tl::expected<std::unique_ptr<AST::WhileLetLoopExpr>, Parse::Error::Node>
1018 30 : Parser<ManagedTokenSource>::parse_while_let_loop_expr (
1019 : AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label)
1020 : {
1021 30 : location_t locus = UNKNOWN_LOCATION;
1022 30 : if (label)
1023 1 : locus = label->get_locus ();
1024 : else
1025 58 : locus = lexer.peek_token ()->get_locus ();
1026 30 : maybe_skip_token (WHILE);
1027 :
1028 : /* check for possible accidental recognition of a while loop as a while let
1029 : * loop */
1030 60 : if (lexer.peek_token ()->get_id () != LET)
1031 : {
1032 0 : Error error (lexer.peek_token ()->get_locus (),
1033 : "appears to be a while loop but is being parsed by "
1034 : "while let loop - this may be a compiler issue");
1035 0 : add_error (std::move (error));
1036 :
1037 : // skip somewhere
1038 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1039 0 : }
1040 : // as this token is definitely let now, save the computation of comparison
1041 30 : lexer.skip_token ();
1042 :
1043 : // parse predicate patterns
1044 30 : std::unique_ptr<AST::Pattern> predicate_pattern
1045 : = parse_match_arm_pattern (EQUAL);
1046 : // ensure that there is at least 1 pattern
1047 30 : if (predicate_pattern == nullptr)
1048 : {
1049 1 : Error error (lexer.peek_token ()->get_locus (),
1050 : "should be at least 1 pattern");
1051 1 : add_error (std::move (error));
1052 1 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1053 1 : }
1054 :
1055 29 : if (!skip_token (EQUAL))
1056 : {
1057 : // skip somewhere?
1058 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1059 : }
1060 :
1061 : /* parse predicate expression, which is required (and HACK to prevent struct
1062 : * expr) */
1063 29 : ParseRestrictions no_struct_expr;
1064 29 : no_struct_expr.can_be_struct_expr = false;
1065 29 : auto predicate_expr = parse_expr ({}, no_struct_expr);
1066 29 : if (!predicate_expr)
1067 : {
1068 0 : Error error (lexer.peek_token ()->get_locus (),
1069 : "failed to parse predicate expression in while let loop");
1070 0 : add_error (std::move (error));
1071 :
1072 : // skip somewhere?
1073 : return tl::unexpected<Parse::Error::Node> (
1074 0 : Parse::Error::Node::CHILD_ERROR);
1075 0 : }
1076 : /* TODO: ensure that struct expression is not parsed? Actually, probably in
1077 : * semantic analysis. */
1078 :
1079 : // parse loop body, which is required
1080 29 : auto body = parse_block_expr ();
1081 29 : if (!body)
1082 : {
1083 0 : Error error (lexer.peek_token ()->get_locus (),
1084 : "failed to parse block expr (loop body) of while let loop");
1085 0 : add_error (std::move (error));
1086 :
1087 : // skip somewhere?
1088 : return tl::unexpected<Parse::Error::Node> (
1089 0 : Parse::Error::Node::CHILD_ERROR);
1090 0 : }
1091 :
1092 29 : return std::unique_ptr<AST::WhileLetLoopExpr> (
1093 59 : new AST::WhileLetLoopExpr (std::move (predicate_pattern),
1094 29 : std::move (predicate_expr.value ()),
1095 29 : std::move (body.value ()), locus,
1096 29 : std::move (label), std::move (outer_attrs)));
1097 59 : }
1098 :
1099 : /* Parses a "for" iterative loop. Label is not parsed and should be parsed via
1100 : * parse_labelled_loop_expr, which would call this. */
1101 : template <typename ManagedTokenSource>
1102 : tl::expected<std::unique_ptr<AST::ForLoopExpr>, Parse::Error::Node>
1103 222 : Parser<ManagedTokenSource>::parse_for_loop_expr (
1104 : AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label)
1105 : {
1106 222 : location_t locus = UNKNOWN_LOCATION;
1107 222 : if (label)
1108 0 : locus = label->get_locus ();
1109 : else
1110 444 : locus = lexer.peek_token ()->get_locus ();
1111 222 : maybe_skip_token (FOR);
1112 :
1113 : // parse pattern, which is required
1114 222 : std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
1115 222 : if (!pattern)
1116 : {
1117 0 : Error error (lexer.peek_token ()->get_locus (),
1118 : "failed to parse iterator pattern in for loop");
1119 0 : add_error (std::move (error));
1120 :
1121 : // skip somewhere?
1122 : return tl::unexpected<Parse::Error::Node> (
1123 0 : Parse::Error::Node::CHILD_ERROR);
1124 0 : }
1125 :
1126 222 : if (!skip_token (IN))
1127 : {
1128 : // skip somewhere?
1129 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1130 : }
1131 :
1132 : /* parse iterator expression, which is required - also HACK to prevent
1133 : * struct expr */
1134 222 : ParseRestrictions no_struct_expr;
1135 222 : no_struct_expr.can_be_struct_expr = false;
1136 222 : auto expr = parse_expr ({}, no_struct_expr);
1137 222 : if (!expr)
1138 : {
1139 0 : Error error (lexer.peek_token ()->get_locus (),
1140 : "failed to parse iterator expression in for loop");
1141 0 : add_error (std::move (error));
1142 :
1143 : // skip somewhere?
1144 : return tl::unexpected<Parse::Error::Node> (
1145 0 : Parse::Error::Node::CHILD_ERROR);
1146 0 : }
1147 : // TODO: check to ensure this isn't struct expr? Or in semantic analysis.
1148 :
1149 : // parse loop body, which is required
1150 222 : auto body = parse_block_expr ();
1151 222 : if (!body)
1152 : {
1153 0 : Error error (lexer.peek_token ()->get_locus (),
1154 : "failed to parse loop body block expression in for loop");
1155 0 : add_error (std::move (error));
1156 :
1157 : // skip somewhere?
1158 : return tl::unexpected<Parse::Error::Node> (
1159 0 : Parse::Error::Node::CHILD_ERROR);
1160 0 : }
1161 222 : return std::unique_ptr<AST::ForLoopExpr> (
1162 444 : new AST::ForLoopExpr (std::move (pattern), std::move (expr.value ()),
1163 222 : std::move (body.value ()), locus, std::move (label),
1164 222 : std::move (outer_attrs)));
1165 444 : }
1166 :
1167 : // Parses a loop expression with label (any kind of loop - disambiguates).
1168 : template <typename ManagedTokenSource>
1169 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Node>
1170 60 : Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok,
1171 : AST::AttrVec outer_attrs)
1172 : {
1173 : // parse loop label (required)
1174 120 : auto parsed_label = parse_loop_label (tok);
1175 60 : if (!parsed_label)
1176 : {
1177 : /* TODO: decide whether it should not work if there is no label, or parse
1178 : * it with no label at the moment, I will make it not work with no label
1179 : * because that's the implication. */
1180 :
1181 0 : if (parsed_label.error ().kind
1182 : == Parse::Error::LoopLabel::Kind::NOT_LOOP_LABEL)
1183 : {
1184 0 : Error error (tok->get_locus (),
1185 : "expected lifetime in labelled loop expr (to parse loop "
1186 : "label) - found %qs",
1187 : tok->get_token_description ());
1188 0 : add_error (std::move (error));
1189 : return tl::unexpected<Parse::Error::Node> (
1190 0 : Parse::Error::Node::CHILD_ERROR);
1191 0 : }
1192 :
1193 : else
1194 : {
1195 0 : Error error (lexer.peek_token ()->get_locus (),
1196 : "failed to parse loop label in labelled loop expr");
1197 0 : add_error (std::move (error));
1198 :
1199 : // skip?
1200 : return tl::unexpected<Parse::Error::Node> (
1201 0 : Parse::Error::Node::CHILD_ERROR);
1202 0 : }
1203 : }
1204 :
1205 60 : auto label = parsed_label
1206 : ? tl::optional<AST::LoopLabel> (parsed_label.value ())
1207 : : tl::nullopt;
1208 :
1209 : // branch on next token
1210 60 : const_TokenPtr t = lexer.peek_token ();
1211 60 : switch (t->get_id ())
1212 : {
1213 49 : case LOOP:
1214 147 : return parse_loop_expr (std::move (outer_attrs), std::move (label));
1215 0 : case FOR:
1216 0 : return parse_for_loop_expr (std::move (outer_attrs), std::move (label));
1217 8 : case WHILE:
1218 : // further disambiguate into while vs while let
1219 16 : if (lexer.peek_token (1)->get_id () == LET)
1220 3 : return parse_while_let_loop_expr (std::move (outer_attrs),
1221 1 : std::move (label));
1222 : else
1223 21 : return parse_while_loop_expr (std::move (outer_attrs),
1224 7 : std::move (label));
1225 3 : case LEFT_CURLY:
1226 9 : return parse_block_expr (std::move (outer_attrs), std::move (label));
1227 0 : default:
1228 : // error
1229 0 : add_error (Error (t->get_locus (),
1230 : "unexpected token %qs when parsing labelled loop",
1231 : t->get_token_description ()));
1232 :
1233 : // skip?
1234 : return tl::unexpected<Parse::Error::Node> (
1235 0 : Parse::Error::Node::CHILD_ERROR);
1236 : }
1237 120 : }
1238 :
1239 : // Parses a match expression.
1240 : template <typename ManagedTokenSource>
1241 : tl::expected<std::unique_ptr<AST::MatchExpr>, Parse::Error::Node>
1242 5568 : Parser<ManagedTokenSource>::parse_match_expr (AST::AttrVec outer_attrs,
1243 : location_t pratt_parsed_loc)
1244 : {
1245 5568 : location_t locus = pratt_parsed_loc;
1246 5568 : if (locus == UNKNOWN_LOCATION)
1247 : {
1248 0 : locus = lexer.peek_token ()->get_locus ();
1249 0 : skip_token (MATCH_KW);
1250 : }
1251 :
1252 : /* parse scrutinee expression, which is required (and HACK to prevent struct
1253 : * expr) */
1254 5568 : ParseRestrictions no_struct_expr;
1255 5568 : no_struct_expr.can_be_struct_expr = false;
1256 5568 : auto scrutinee = parse_expr ({}, no_struct_expr);
1257 5568 : if (!scrutinee)
1258 : {
1259 1 : Error error (lexer.peek_token ()->get_locus (),
1260 : "failed to parse scrutinee expression in match expression");
1261 1 : add_error (std::move (error));
1262 :
1263 : // skip somewhere?
1264 : return tl::unexpected<Parse::Error::Node> (
1265 1 : Parse::Error::Node::CHILD_ERROR);
1266 1 : }
1267 : /* TODO: check for scrutinee expr not being struct expr? or do so in
1268 : * semantic analysis */
1269 :
1270 5567 : if (!skip_token (LEFT_CURLY))
1271 : {
1272 : // skip somewhere?
1273 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1274 : }
1275 :
1276 : // parse inner attributes (if they exist)
1277 5567 : AST::AttrVec inner_attrs = parse_inner_attributes ();
1278 :
1279 : // parse match arms (if they exist)
1280 : // std::vector<std::unique_ptr<AST::MatchCase> > match_arms;
1281 5567 : std::vector<AST::MatchCase> match_arms;
1282 :
1283 : // parse match cases
1284 160575 : while (lexer.peek_token ()->get_id () != RIGHT_CURLY)
1285 : {
1286 : // parse match arm itself, which is required
1287 49943 : AST::MatchArm arm = parse_match_arm ();
1288 49943 : if (arm.is_error ())
1289 : {
1290 : // TODO is this worth throwing everything away?
1291 0 : Error error (lexer.peek_token ()->get_locus (),
1292 : "failed to parse match arm in match arms");
1293 0 : add_error (std::move (error));
1294 :
1295 : return tl::unexpected<Parse::Error::Node> (
1296 0 : Parse::Error::Node::CHILD_ERROR);
1297 0 : }
1298 :
1299 49943 : if (!skip_token (MATCH_ARROW))
1300 : {
1301 : // skip after somewhere?
1302 : // TODO is returning here a good idea? or is break better?
1303 : return tl::unexpected<Parse::Error::Node> (
1304 0 : Parse::Error::Node::MALFORMED);
1305 : }
1306 :
1307 49943 : ParseRestrictions restrictions;
1308 49943 : restrictions.expr_can_be_stmt = true;
1309 :
1310 49943 : auto expr = parse_expr ({}, restrictions);
1311 :
1312 49943 : if (!expr)
1313 : {
1314 : /* We don't need to throw an error as it already reported by
1315 : * parse_expr
1316 : */
1317 : return tl::unexpected<Parse::Error::Node> (
1318 2 : Parse::Error::Node::CHILD_ERROR);
1319 : }
1320 :
1321 49941 : bool is_expr_without_block = expr.value ()->is_expr_without_block ();
1322 :
1323 49941 : match_arms.push_back (
1324 99882 : AST::MatchCase (std::move (arm), std::move (expr.value ())));
1325 :
1326 : // handle comma presence
1327 99882 : if (lexer.peek_token ()->get_id () != COMMA)
1328 : {
1329 1065 : if (!is_expr_without_block)
1330 : {
1331 : // allowed even if not final case
1332 : continue;
1333 : }
1334 192 : else if (is_expr_without_block
1335 384 : && lexer.peek_token ()->get_id () != RIGHT_CURLY)
1336 : {
1337 : // not allowed if not final case
1338 1 : Error error (lexer.peek_token ()->get_locus (),
1339 : "exprwithoutblock requires comma after match case "
1340 : "expression in match arm (if not final case)");
1341 1 : add_error (std::move (error));
1342 :
1343 : return tl::unexpected<Parse::Error::Node> (
1344 1 : Parse::Error::Node::MALFORMED);
1345 1 : }
1346 : else
1347 : {
1348 : // otherwise, must be final case, so fine
1349 : break;
1350 : }
1351 : }
1352 48876 : lexer.skip_token ();
1353 : }
1354 :
1355 5564 : if (!skip_token (RIGHT_CURLY))
1356 : {
1357 : // skip somewhere?
1358 0 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1359 : }
1360 :
1361 5564 : match_arms.shrink_to_fit ();
1362 :
1363 5564 : return std::unique_ptr<AST::MatchExpr> (
1364 5564 : new AST::MatchExpr (std::move (scrutinee.value ()), std::move (match_arms),
1365 : std::move (inner_attrs), std::move (outer_attrs),
1366 5564 : locus));
1367 5567 : }
1368 :
1369 : // Parses an async block expression.
1370 : template <typename ManagedTokenSource>
1371 : tl::expected<std::unique_ptr<AST::AsyncBlockExpr>, Parse::Error::Node>
1372 0 : Parser<ManagedTokenSource>::parse_async_block_expr (AST::AttrVec outer_attrs)
1373 : {
1374 0 : location_t locus = lexer.peek_token ()->get_locus ();
1375 0 : skip_token (ASYNC);
1376 :
1377 : // detect optional move token
1378 0 : bool has_move = false;
1379 0 : if (lexer.peek_token ()->get_id () == MOVE)
1380 : {
1381 0 : lexer.skip_token ();
1382 0 : has_move = true;
1383 : }
1384 :
1385 : // parse block expression (required)
1386 0 : auto block_expr = parse_block_expr ();
1387 0 : if (!block_expr)
1388 : {
1389 0 : Error error (
1390 0 : lexer.peek_token ()->get_locus (),
1391 : "failed to parse block expression of async block expression");
1392 0 : add_error (std::move (error));
1393 :
1394 : // skip somewhere?
1395 : return tl::unexpected<Parse::Error::Node> (
1396 0 : Parse::Error::Node::CHILD_ERROR);
1397 0 : }
1398 :
1399 0 : return std::unique_ptr<AST::AsyncBlockExpr> (
1400 0 : new AST::AsyncBlockExpr (std::move (block_expr.value ()), has_move,
1401 0 : std::move (outer_attrs), locus));
1402 0 : }
1403 :
1404 : // Parses an unsafe block expression.
1405 : template <typename ManagedTokenSource>
1406 : tl::expected<std::unique_ptr<AST::UnsafeBlockExpr>, Parse::Error::Node>
1407 4817 : Parser<ManagedTokenSource>::parse_unsafe_block_expr (
1408 : AST::AttrVec outer_attrs, location_t pratt_parsed_loc)
1409 : {
1410 4817 : location_t locus = pratt_parsed_loc;
1411 4817 : if (locus == UNKNOWN_LOCATION)
1412 : {
1413 0 : locus = lexer.peek_token ()->get_locus ();
1414 0 : skip_token (UNSAFE);
1415 : }
1416 :
1417 : // parse block expression (required)
1418 4817 : auto block_expr = parse_block_expr ();
1419 4817 : if (!block_expr)
1420 : {
1421 0 : Error error (
1422 0 : lexer.peek_token ()->get_locus (),
1423 : "failed to parse block expression of unsafe block expression");
1424 0 : add_error (std::move (error));
1425 :
1426 : // skip somewhere?
1427 : return tl::unexpected<Parse::Error::Node> (
1428 0 : Parse::Error::Node::CHILD_ERROR);
1429 0 : }
1430 4817 : return std::unique_ptr<AST::UnsafeBlockExpr> (
1431 4817 : new AST::UnsafeBlockExpr (std::move (block_expr.value ()),
1432 4817 : std::move (outer_attrs), locus));
1433 4817 : }
1434 :
1435 : // Parses an array definition expression.
1436 : template <typename ManagedTokenSource>
1437 : tl::expected<std::unique_ptr<AST::ArrayExpr>, Parse::Error::Node>
1438 13213 : Parser<ManagedTokenSource>::parse_array_expr (AST::AttrVec outer_attrs,
1439 : location_t pratt_parsed_loc)
1440 : {
1441 13213 : location_t locus = pratt_parsed_loc;
1442 13213 : if (locus == UNKNOWN_LOCATION)
1443 : {
1444 0 : locus = lexer.peek_token ()->get_locus ();
1445 0 : skip_token (LEFT_SQUARE);
1446 : }
1447 :
1448 : // parse optional inner attributes
1449 13213 : AST::AttrVec inner_attrs = parse_inner_attributes ();
1450 :
1451 : // parse the "array elements" section, which is optional
1452 26426 : if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
1453 : {
1454 : // no array elements
1455 57 : lexer.skip_token ();
1456 :
1457 57 : std::vector<std::unique_ptr<AST::Expr>> exprs;
1458 57 : auto array_elems
1459 : = std::make_unique<AST::ArrayElemsValues> (std::move (exprs), locus);
1460 57 : return std::make_unique<AST::ArrayExpr> (std::move (array_elems),
1461 : std::move (inner_attrs),
1462 57 : std::move (outer_attrs), locus);
1463 57 : }
1464 : else
1465 : {
1466 : // should have array elements
1467 : // parse initial expression, which is required for either
1468 13156 : auto initial_expr = parse_expr ();
1469 13156 : if (!initial_expr)
1470 : {
1471 0 : Error error (lexer.peek_token ()->get_locus (),
1472 : "could not parse expression in array expression "
1473 : "(even though arrayelems seems to be present)");
1474 0 : add_error (std::move (error));
1475 :
1476 : // skip somewhere?
1477 : return tl::unexpected<Parse::Error::Node> (
1478 0 : Parse::Error::Node::CHILD_ERROR);
1479 0 : }
1480 :
1481 26312 : if (lexer.peek_token ()->get_id () == SEMICOLON)
1482 : {
1483 : // copy array elems
1484 260 : lexer.skip_token ();
1485 :
1486 : // parse copy amount expression (required)
1487 260 : auto copy_amount = parse_expr ();
1488 260 : if (!copy_amount)
1489 : {
1490 0 : Error error (lexer.peek_token ()->get_locus (),
1491 : "could not parse copy amount expression in array "
1492 : "expression (arrayelems)");
1493 0 : add_error (std::move (error));
1494 :
1495 : // skip somewhere?
1496 : return tl::unexpected<Parse::Error::Node> (
1497 0 : Parse::Error::Node::CHILD_ERROR);
1498 0 : }
1499 :
1500 260 : skip_token (RIGHT_SQUARE);
1501 :
1502 260 : std::unique_ptr<AST::ArrayElemsCopied> copied_array_elems (
1503 520 : new AST::ArrayElemsCopied (std::move (initial_expr.value ()),
1504 260 : std::move (copy_amount.value ()),
1505 : locus));
1506 260 : return std::unique_ptr<AST::ArrayExpr> (
1507 260 : new AST::ArrayExpr (std::move (copied_array_elems),
1508 : std::move (inner_attrs),
1509 260 : std::move (outer_attrs), locus));
1510 520 : }
1511 25792 : else if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
1512 : {
1513 : // single-element array expression
1514 36 : std::vector<std::unique_ptr<AST::Expr>> exprs;
1515 36 : exprs.reserve (1);
1516 36 : exprs.push_back (std::move (initial_expr.value ()));
1517 36 : exprs.shrink_to_fit ();
1518 :
1519 36 : skip_token (RIGHT_SQUARE);
1520 :
1521 36 : std::unique_ptr<AST::ArrayElemsValues> array_elems (
1522 36 : new AST::ArrayElemsValues (std::move (exprs), locus));
1523 36 : return std::unique_ptr<AST::ArrayExpr> (
1524 36 : new AST::ArrayExpr (std::move (array_elems),
1525 : std::move (inner_attrs),
1526 36 : std::move (outer_attrs), locus));
1527 36 : }
1528 25720 : else if (lexer.peek_token ()->get_id () == COMMA)
1529 : {
1530 : // multi-element array expression (or trailing comma)
1531 12860 : std::vector<std::unique_ptr<AST::Expr>> exprs;
1532 12860 : exprs.push_back (std::move (initial_expr.value ()));
1533 :
1534 12860 : const_TokenPtr t = lexer.peek_token ();
1535 123515 : while (t->get_id () == COMMA)
1536 : {
1537 114620 : lexer.skip_token ();
1538 :
1539 : // quick break if right square bracket
1540 229240 : if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
1541 : break;
1542 :
1543 : // parse expression (required)
1544 110655 : auto expr = parse_expr ();
1545 110655 : if (!expr)
1546 : {
1547 0 : Error error (lexer.peek_token ()->get_locus (),
1548 : "failed to parse element in array expression");
1549 0 : add_error (std::move (error));
1550 :
1551 : // skip somewhere?
1552 : return tl::unexpected<Parse::Error::Node> (
1553 0 : Parse::Error::Node::CHILD_ERROR);
1554 0 : }
1555 110655 : exprs.push_back (std::move (expr.value ()));
1556 :
1557 110655 : t = lexer.peek_token ();
1558 : }
1559 :
1560 12860 : skip_token (RIGHT_SQUARE);
1561 :
1562 12860 : exprs.shrink_to_fit ();
1563 :
1564 12860 : std::unique_ptr<AST::ArrayElemsValues> array_elems (
1565 12860 : new AST::ArrayElemsValues (std::move (exprs), locus));
1566 12860 : return std::unique_ptr<AST::ArrayExpr> (
1567 12860 : new AST::ArrayExpr (std::move (array_elems),
1568 : std::move (inner_attrs),
1569 12860 : std::move (outer_attrs), locus));
1570 25720 : }
1571 : else
1572 : {
1573 : // error
1574 0 : Error error (lexer.peek_token ()->get_locus (),
1575 : "unexpected token %qs in array expression (arrayelems)",
1576 0 : lexer.peek_token ()->get_token_description ());
1577 0 : add_error (std::move (error));
1578 :
1579 : // skip somewhere?
1580 : return tl::unexpected<Parse::Error::Node> (
1581 0 : Parse::Error::Node::MALFORMED);
1582 0 : }
1583 13156 : }
1584 13213 : }
1585 :
1586 : // Parses a grouped or tuple expression (disambiguates).
1587 : template <typename ManagedTokenSource>
1588 : tl::expected<std::unique_ptr<AST::ExprWithoutBlock>, Parse::Error::Node>
1589 12597 : Parser<ManagedTokenSource>::parse_grouped_or_tuple_expr (
1590 : AST::AttrVec outer_attrs, location_t pratt_parsed_loc)
1591 : {
1592 : // adjustment to allow Pratt parsing to reuse function without copy-paste
1593 12597 : location_t locus = pratt_parsed_loc;
1594 12597 : if (locus == UNKNOWN_LOCATION)
1595 : {
1596 0 : locus = lexer.peek_token ()->get_locus ();
1597 0 : skip_token (LEFT_PAREN);
1598 : }
1599 :
1600 : // parse optional inner attributes
1601 12597 : AST::AttrVec inner_attrs = parse_inner_attributes ();
1602 :
1603 25194 : if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
1604 : {
1605 : // must be empty tuple
1606 332 : lexer.skip_token ();
1607 :
1608 : // create tuple with empty tuple elems
1609 332 : return std::unique_ptr<AST::TupleExpr> (
1610 332 : new AST::TupleExpr (std::vector<std::unique_ptr<AST::Expr>> (),
1611 : std::move (inner_attrs), std::move (outer_attrs),
1612 332 : locus));
1613 : }
1614 :
1615 : // parse first expression (required)
1616 12265 : auto first_expr = parse_expr ();
1617 12265 : if (!first_expr)
1618 : {
1619 0 : Error error (lexer.peek_token ()->get_locus (),
1620 : "failed to parse expression in grouped or tuple expression");
1621 0 : add_error (std::move (error));
1622 :
1623 : // skip after somewhere?
1624 : return tl::unexpected<Parse::Error::Node> (
1625 0 : Parse::Error::Node::CHILD_ERROR);
1626 0 : }
1627 :
1628 : // detect whether grouped expression with right parentheses as next token
1629 24530 : if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
1630 : {
1631 : // must be grouped expr
1632 8177 : lexer.skip_token ();
1633 :
1634 : // create grouped expr
1635 8177 : return std::unique_ptr<AST::GroupedExpr> (
1636 8177 : new AST::GroupedExpr (std::move (first_expr.value ()),
1637 : std::move (inner_attrs), std::move (outer_attrs),
1638 8177 : locus));
1639 : }
1640 8176 : else if (lexer.peek_token ()->get_id () == COMMA)
1641 : {
1642 : // tuple expr
1643 4087 : std::vector<std::unique_ptr<AST::Expr>> exprs;
1644 4087 : exprs.push_back (std::move (first_expr.value ()));
1645 :
1646 : // parse potential other tuple exprs
1647 4087 : const_TokenPtr t = lexer.peek_token ();
1648 8460 : while (t->get_id () == COMMA)
1649 : {
1650 4438 : lexer.skip_token ();
1651 :
1652 : // break out if right paren
1653 8876 : if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
1654 : break;
1655 :
1656 : // parse expr, which is now required
1657 4373 : auto expr = parse_expr ();
1658 4373 : if (!expr)
1659 : {
1660 0 : Error error (lexer.peek_token ()->get_locus (),
1661 : "failed to parse expr in tuple expr");
1662 0 : add_error (std::move (error));
1663 :
1664 : // skip somewhere?
1665 : return tl::unexpected<Parse::Error::Node> (
1666 0 : Parse::Error::Node::CHILD_ERROR);
1667 0 : }
1668 4373 : exprs.push_back (std::move (expr.value ()));
1669 :
1670 4373 : t = lexer.peek_token ();
1671 : }
1672 :
1673 : // skip right paren
1674 4087 : skip_token (RIGHT_PAREN);
1675 :
1676 4087 : return std::unique_ptr<AST::TupleExpr> (
1677 4087 : new AST::TupleExpr (std::move (exprs), std::move (inner_attrs),
1678 4087 : std::move (outer_attrs), locus));
1679 4087 : }
1680 : else
1681 : {
1682 : // error
1683 1 : const_TokenPtr t = lexer.peek_token ();
1684 1 : Error error (t->get_locus (),
1685 : "unexpected token %qs in grouped or tuple expression "
1686 : "(parenthesised expression) - expected %<)%> for grouped "
1687 : "expr and %<,%> for tuple expr",
1688 : t->get_token_description ());
1689 1 : add_error (std::move (error));
1690 :
1691 : // skip somewhere?
1692 1 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
1693 2 : }
1694 12597 : }
1695 :
1696 : // Parses a struct expression field.
1697 : template <typename ManagedTokenSource>
1698 : tl::expected<std::unique_ptr<AST::StructExprField>,
1699 : Parse::Error::StructExprField>
1700 2943 : Parser<ManagedTokenSource>::parse_struct_expr_field ()
1701 : {
1702 2943 : AST::AttrVec outer_attrs = parse_outer_attributes ();
1703 2943 : const_TokenPtr t = lexer.peek_token ();
1704 2943 : switch (t->get_id ())
1705 : {
1706 2898 : case IDENTIFIER:
1707 5796 : if (lexer.peek_token (1)->get_id () == COLON)
1708 : {
1709 : // struct expr field with identifier and expr
1710 2497 : Identifier ident = {t};
1711 2497 : lexer.skip_token (1);
1712 :
1713 : // parse expression (required)
1714 2497 : auto expr = parse_expr ();
1715 2497 : if (!expr)
1716 : {
1717 0 : Error error (t->get_locus (),
1718 : "failed to parse struct expression field with "
1719 : "identifier and expression");
1720 0 : add_error (std::move (error));
1721 :
1722 : return tl::unexpected<Parse::Error::StructExprField> (
1723 0 : Parse::Error::StructExprField::CHILD_ERROR);
1724 0 : }
1725 :
1726 2497 : return std::unique_ptr<AST::StructExprFieldIdentifierValue> (
1727 4994 : new AST::StructExprFieldIdentifierValue (std::move (ident),
1728 2497 : std::move (expr.value ()),
1729 : std::move (outer_attrs),
1730 2497 : t->get_locus ()));
1731 2497 : }
1732 : else
1733 : {
1734 : // struct expr field with identifier only
1735 401 : Identifier ident{t};
1736 401 : lexer.skip_token ();
1737 :
1738 401 : return std::unique_ptr<AST::StructExprFieldIdentifier> (
1739 802 : new AST::StructExprFieldIdentifier (std::move (ident),
1740 : std::move (outer_attrs),
1741 401 : t->get_locus ()));
1742 401 : }
1743 44 : case INT_LITERAL:
1744 : {
1745 : // parse tuple index field
1746 44 : int index = atoi (t->get_str ().c_str ());
1747 44 : lexer.skip_token ();
1748 :
1749 44 : if (!skip_token (COLON))
1750 : {
1751 : // skip somewhere?
1752 : return tl::unexpected<Parse::Error::StructExprField> (
1753 0 : Parse::Error::StructExprField::MALFORMED);
1754 : }
1755 :
1756 : // parse field expression (required)
1757 44 : auto expr = parse_expr ();
1758 44 : if (!expr)
1759 : {
1760 0 : Error error (t->get_locus (),
1761 : "failed to parse expr in struct (or enum) expr "
1762 : "field with tuple index");
1763 0 : add_error (std::move (error));
1764 :
1765 : return tl::unexpected<Parse::Error::StructExprField> (
1766 0 : Parse::Error::StructExprField::CHILD_ERROR);
1767 0 : }
1768 :
1769 44 : return std::unique_ptr<AST::StructExprFieldIndexValue> (
1770 44 : new AST::StructExprFieldIndexValue (index, std::move (expr.value ()),
1771 : std::move (outer_attrs),
1772 44 : t->get_locus ()));
1773 44 : }
1774 1 : case DOT_DOT:
1775 : /* this is a struct base and can't be parsed here, so just return
1776 : * nothing without erroring */
1777 1 : if (!outer_attrs.empty ())
1778 : {
1779 1 : add_error (
1780 1 : Error (t->get_locus (),
1781 : "attributes are not allowed before %<..%> in a struct "
1782 : "expression"));
1783 :
1784 : return tl::unexpected<Parse::Error::StructExprField> (
1785 1 : Parse::Error::StructExprField::STRUCT_BASE_ATTRIBUTES);
1786 : }
1787 :
1788 : return tl::unexpected<Parse::Error::StructExprField> (
1789 0 : Parse::Error::StructExprField::STRUCT_BASE);
1790 0 : default:
1791 0 : add_error (
1792 0 : Error (t->get_locus (),
1793 : "unrecognised token %qs as first token of struct expr field - "
1794 : "expected identifier or integer literal",
1795 : t->get_token_description ()));
1796 :
1797 : return tl::unexpected<Parse::Error::StructExprField> (
1798 0 : Parse::Error::StructExprField::MALFORMED);
1799 : }
1800 2943 : }
1801 :
1802 : /* Pratt parser impl of parse_expr. FIXME: this is only provisional and
1803 : * probably will be changed. */
1804 : template <typename ManagedTokenSource>
1805 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
1806 735484 : Parser<ManagedTokenSource>::parse_expr (int right_binding_power,
1807 : AST::AttrVec outer_attrs,
1808 : ParseRestrictions restrictions)
1809 : {
1810 735484 : const_TokenPtr current_token = lexer.peek_token ();
1811 : // Special hack because we are allowed to return nullptr, in that case we
1812 : // don't want to skip the token, since we don't actually parse it. But if
1813 : // null isn't allowed it indicates an error, and we want to skip past that.
1814 : // So return early if it is one of the tokens that ends an expression
1815 : // (or at least cannot start a new expression).
1816 735484 : if (restrictions.expr_can_be_null)
1817 : {
1818 5914 : TokenId id = current_token->get_id ();
1819 5914 : if (id == SEMICOLON || id == RIGHT_PAREN || id == RIGHT_CURLY
1820 : || id == RIGHT_SQUARE || id == COMMA || id == LEFT_CURLY)
1821 : return tl::unexpected<Parse::Error::Expr> (
1822 274 : Parse::Error::Expr::NULL_EXPR);
1823 : }
1824 :
1825 735210 : ParseRestrictions null_denotation_restrictions = restrictions;
1826 735210 : null_denotation_restrictions.expr_can_be_stmt = false;
1827 :
1828 : // parse null denotation (unary part of expression)
1829 735210 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr> expr
1830 735210 : = null_denotation ({}, null_denotation_restrictions);
1831 735210 : if (!expr)
1832 66 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
1833 735144 : if (expr.value () == nullptr)
1834 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
1835 :
1836 1470288 : return left_denotations (std::move (expr), right_binding_power,
1837 735144 : std::move (outer_attrs), restrictions);
1838 735210 : }
1839 :
1840 : // Parse expression with lowest left binding power.
1841 : template <typename ManagedTokenSource>
1842 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
1843 677806 : Parser<ManagedTokenSource>::parse_expr (AST::AttrVec outer_attrs,
1844 : ParseRestrictions restrictions)
1845 : {
1846 677806 : return parse_expr (LBP_LOWEST, std::move (outer_attrs), restrictions);
1847 : }
1848 :
1849 : template <typename ManagedTokenSource>
1850 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
1851 765325 : Parser<ManagedTokenSource>::left_denotations (
1852 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr> expr,
1853 : int right_binding_power, AST::AttrVec outer_attrs,
1854 : ParseRestrictions restrictions)
1855 : {
1856 765325 : if (!expr)
1857 : {
1858 : // DEBUG
1859 1 : rust_debug ("null denotation is null; returning null for parse_expr");
1860 : return tl::unexpected<Parse::Error::Expr> (
1861 1 : Parse::Error::Expr::NULL_DENOTATION);
1862 : }
1863 :
1864 765324 : const_TokenPtr current_token = lexer.peek_token ();
1865 :
1866 97754 : if (restrictions.expr_can_be_stmt && !expr.value ()->is_expr_without_block ()
1867 11314 : && current_token->get_id () != DOT
1868 776629 : && current_token->get_id () != QUESTION_MARK)
1869 : {
1870 11305 : rust_debug ("statement expression with block");
1871 11305 : expr.value ()->set_outer_attrs (std::move (outer_attrs));
1872 765324 : return expr;
1873 : }
1874 :
1875 852389 : restrictions.expr_can_be_stmt = false;
1876 :
1877 : // stop parsing if find lower priority token - parse higher priority first
1878 2557167 : while (right_binding_power < left_binding_power (current_token))
1879 : {
1880 98372 : lexer.skip_token ();
1881 :
1882 : // FIXME attributes should generally be applied to the null denotation.
1883 393486 : expr = left_denotation (current_token, std::move (expr.value ()),
1884 : std::move (outer_attrs), restrictions);
1885 :
1886 98372 : if (!expr)
1887 : {
1888 : // DEBUG
1889 2 : rust_debug ("left denotation is null; returning null for parse_expr");
1890 :
1891 : return tl::unexpected<Parse::Error::Expr> (
1892 2 : Parse::Error::Expr::LEFT_DENOTATION);
1893 : }
1894 :
1895 98370 : current_token = lexer.peek_token ();
1896 : }
1897 :
1898 765324 : return expr;
1899 765324 : }
1900 :
1901 : /* Determines action to take when finding token at beginning of expression. */
1902 : template <typename ManagedTokenSource>
1903 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
1904 735210 : Parser<ManagedTokenSource>::null_denotation (AST::AttrVec outer_attrs,
1905 : ParseRestrictions restrictions)
1906 : {
1907 : /* note: tok is previous character in input stream, not current one, as
1908 : * parse_expr skips it before passing it in */
1909 :
1910 : /* as a Pratt parser (which works by decomposing expressions into a null
1911 : * denotation and then a left denotation), null denotations handle primaries
1912 : * and unary operands (but only prefix unary operands) */
1913 :
1914 735210 : auto tok = lexer.peek_token ();
1915 :
1916 735210 : switch (tok->get_id ())
1917 : {
1918 285449 : case IDENTIFIER:
1919 : case SELF:
1920 : case SELF_ALIAS:
1921 : case DOLLAR_SIGN:
1922 : case CRATE:
1923 : case SUPER:
1924 : case SCOPE_RESOLUTION:
1925 : {
1926 : // DEBUG
1927 285449 : rust_debug ("beginning null denotation identifier handling");
1928 :
1929 : /* best option: parse as path, then extract identifier, macro,
1930 : * struct/enum, or just path info from it */
1931 285449 : AST::PathInExpression path = parse_path_in_expression ();
1932 :
1933 570898 : return null_denotation_path (std::move (path), std::move (outer_attrs),
1934 285449 : restrictions);
1935 285449 : }
1936 2 : case HASH:
1937 : {
1938 : // Parse outer attributes and then the expression that follows
1939 2 : AST::AttrVec attrs = parse_outer_attributes ();
1940 :
1941 : // Merge with any existing outer attributes
1942 2 : if (!outer_attrs.empty ())
1943 0 : attrs.insert (attrs.begin (), outer_attrs.begin (),
1944 : outer_attrs.end ());
1945 :
1946 : // Try to parse the expression that should follow the attributes
1947 2 : auto expr = parse_expr (std::move (attrs), restrictions);
1948 2 : if (!expr)
1949 : {
1950 : /* If parsing failed and we're at a semicolon, provide a better
1951 : * error
1952 : */
1953 2 : const_TokenPtr next_tok = lexer.peek_token ();
1954 2 : if (next_tok->get_id () == SEMICOLON)
1955 0 : add_error (Error (next_tok->get_locus (),
1956 : "expected expression, found %<;%>"));
1957 : return tl::unexpected<Parse::Error::Expr> (
1958 2 : Parse::Error::Expr::CHILD_ERROR);
1959 2 : }
1960 0 : return expr;
1961 2 : }
1962 449759 : default:
1963 449759 : if (tok->get_id () == LEFT_SHIFT)
1964 : {
1965 2 : lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
1966 2 : tok = lexer.peek_token ();
1967 : }
1968 :
1969 449759 : lexer.skip_token ();
1970 899518 : return null_denotation_not_path (std::move (tok), std::move (outer_attrs),
1971 449759 : restrictions);
1972 : }
1973 735210 : }
1974 :
1975 : // Handling of expresions that start with a path for `null_denotation`.
1976 : template <typename ManagedTokenSource>
1977 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
1978 314468 : Parser<ManagedTokenSource>::null_denotation_path (
1979 : AST::PathInExpression path, AST::AttrVec outer_attrs,
1980 : ParseRestrictions restrictions)
1981 : {
1982 314468 : rust_debug ("parsing null denotation after path");
1983 :
1984 : // HACK: always make "self" by itself a path (regardless of next
1985 : // tokens)
1986 314468 : if (path.is_single_segment () && path.get_segments ()[0].is_lower_self_seg ())
1987 : {
1988 : // HACK: add outer attrs to path
1989 20106 : path.set_outer_attrs (std::move (outer_attrs));
1990 40212 : return std::make_unique<AST::PathInExpression> (std::move (path));
1991 : }
1992 :
1993 : // branch on next token
1994 294362 : const_TokenPtr t = lexer.peek_token ();
1995 294362 : switch (t->get_id ())
1996 : {
1997 50647 : case EXCLAM:
1998 : {
1999 : // macro
2000 50647 : auto macro = parse_macro_invocation_partial (std::move (path),
2001 : std::move (outer_attrs));
2002 50647 : if (macro == nullptr)
2003 : return tl::unexpected<Parse::Error::Expr> (
2004 3 : Parse::Error::Expr::CHILD_ERROR);
2005 50644 : return std::unique_ptr<AST::Expr> (std::move (macro));
2006 50647 : }
2007 3893 : case LEFT_CURLY:
2008 : {
2009 3893 : bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER
2010 10574 : && (lexer.peek_token (2)->get_id () == COMMA
2011 9423 : || (lexer.peek_token (2)->get_id () == COLON
2012 6174 : && (lexer.peek_token (4)->get_id () == COMMA
2013 858 : || !Parse::Utils::can_tok_start_type (
2014 2048 : lexer.peek_token (3)->get_id ()))));
2015 :
2016 : /* definitely not a block:
2017 : * path '{' ident ','
2018 : * path '{' ident ':' [anything] ','
2019 : * path '{' ident ':' [not a type]
2020 : * otherwise, assume block expr and thus path */
2021 : // DEBUG
2022 15572 : rust_debug ("values of lookahead: '%s' '%s' '%s' '%s' ",
2023 : lexer.peek_token (1)->get_token_description (),
2024 : lexer.peek_token (2)->get_token_description (),
2025 : lexer.peek_token (3)->get_token_description (),
2026 : lexer.peek_token (4)->get_token_description ());
2027 :
2028 8726 : rust_debug ("can be struct expr: '%s', not a block: '%s'",
2029 : restrictions.can_be_struct_expr ? "true" : "false",
2030 : not_a_block ? "true" : "false");
2031 :
2032 : // struct/enum expr struct
2033 3893 : if (!restrictions.can_be_struct_expr && !not_a_block)
2034 : {
2035 : // HACK: add outer attrs to path
2036 2136 : path.set_outer_attrs (std::move (outer_attrs));
2037 2136 : return std::unique_ptr<AST::PathInExpression> (
2038 2136 : new AST::PathInExpression (std::move (path)));
2039 : }
2040 1757 : auto struct_expr
2041 3514 : = parse_struct_expr_struct_partial (std::move (path),
2042 : std::move (outer_attrs));
2043 1757 : if (struct_expr == nullptr)
2044 : {
2045 : return tl::unexpected<Parse::Error::Expr> (
2046 0 : Parse::Error::Expr::CHILD_ERROR);
2047 : }
2048 1757 : return struct_expr;
2049 1757 : }
2050 80824 : case LEFT_PAREN:
2051 : {
2052 : // struct/enum expr tuple
2053 80824 : if (!restrictions.can_be_struct_expr)
2054 : {
2055 : // assume path is returned
2056 : // HACK: add outer attributes to path
2057 1087 : path.set_outer_attrs (std::move (outer_attrs));
2058 2174 : return std::make_unique<AST::PathInExpression> (std::move (path));
2059 : }
2060 79737 : auto tuple_expr
2061 159474 : = parse_struct_expr_tuple_partial (std::move (path),
2062 : std::move (outer_attrs));
2063 79737 : if (tuple_expr == nullptr)
2064 : {
2065 : return tl::unexpected<Parse::Error::Expr> (
2066 0 : Parse::Error::Expr::CHILD_ERROR);
2067 : }
2068 79737 : return tuple_expr;
2069 79737 : }
2070 158998 : default:
2071 : // assume path is returned if not single segment
2072 158998 : if (path.is_single_segment ())
2073 : {
2074 : // FIXME: This should probably be returned as a path.
2075 : /* HACK: may have to become permanent, but this is my current
2076 : * identifier expression */
2077 468231 : return std::unique_ptr<AST::IdentifierExpr> (new AST::IdentifierExpr (
2078 624308 : path.get_segments ()[0].get_ident_segment ().as_string (), {},
2079 156077 : path.get_locus ()));
2080 : }
2081 : // HACK: add outer attrs to path
2082 2921 : path.set_outer_attrs (std::move (outer_attrs));
2083 2921 : return std::unique_ptr<AST::PathInExpression> (
2084 2921 : new AST::PathInExpression (std::move (path)));
2085 : }
2086 : rust_unreachable ();
2087 294362 : }
2088 :
2089 : // Handling of expresions that do not start with a path for `null_denotation`.
2090 : template <typename ManagedTokenSource>
2091 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
2092 449759 : Parser<ManagedTokenSource>::null_denotation_not_path (
2093 : const_TokenPtr tok, AST::AttrVec outer_attrs, ParseRestrictions restrictions)
2094 : {
2095 449759 : switch (tok->get_id ())
2096 : {
2097 : // FIXME: Handle in null_denotation_path?
2098 189 : case LEFT_SHIFT:
2099 : case LEFT_ANGLE:
2100 : {
2101 : // qualified path
2102 : // HACK: add outer attrs to path
2103 189 : AST::QualifiedPathInExpression path
2104 : = parse_qualified_path_in_expression (tok->get_locus ());
2105 189 : path.set_outer_attrs (std::move (outer_attrs));
2106 189 : return std::make_unique<AST::QualifiedPathInExpression> (
2107 189 : std::move (path));
2108 189 : }
2109 : // FIXME: delegate to parse_literal_expr instead? would have to rejig
2110 : // tokens and whatever.
2111 : // FIXME: for literal exprs, outer attrs should be passed in, and later
2112 : // error if it does not make up the entire statement.
2113 353398 : case INT_LITERAL:
2114 : // we should check the range, but ignore for now
2115 : // encode as int?
2116 1413592 : return std::unique_ptr<AST::LiteralExpr> (new AST::LiteralExpr (
2117 1060194 : LiteralResolve::evaluate_integer_literal (tok), AST::Literal::INT,
2118 1060194 : LiteralResolve::resolve_literal_suffix (tok), {}, tok->get_locus ()));
2119 13777 : case FLOAT_LITERAL:
2120 : // encode as float?
2121 55108 : return std::unique_ptr<AST::LiteralExpr> (new AST::LiteralExpr (
2122 41331 : LiteralResolve::evaluate_float_literal (tok), AST::Literal::FLOAT,
2123 41331 : LiteralResolve::resolve_literal_suffix (tok), {}, tok->get_locus ()));
2124 6213 : case STRING_LITERAL:
2125 6213 : return std::unique_ptr<AST::LiteralExpr> (
2126 24852 : new AST::LiteralExpr (tok->get_str (), AST::Literal::STRING,
2127 6213 : tok->get_type_hint (), {}, tok->get_locus ()));
2128 138 : case BYTE_STRING_LITERAL:
2129 138 : return std::unique_ptr<AST::LiteralExpr> (
2130 552 : new AST::LiteralExpr (tok->get_str (), AST::Literal::BYTE_STRING,
2131 138 : tok->get_type_hint (), {}, tok->get_locus ()));
2132 103 : case RAW_STRING_LITERAL:
2133 103 : return std::unique_ptr<AST::LiteralExpr> (
2134 412 : new AST::LiteralExpr (tok->get_str (), AST::Literal::RAW_STRING,
2135 103 : tok->get_type_hint (), {}, tok->get_locus ()));
2136 15 : case C_STRING_LITERAL:
2137 15 : if (flag_c_style_string_literals)
2138 : {
2139 15 : return std::unique_ptr<AST::LiteralExpr> (
2140 60 : new AST::LiteralExpr (tok->get_str (), AST::Literal::C_STRING,
2141 : tok->get_type_hint (), {},
2142 15 : tok->get_locus ()));
2143 : }
2144 : else
2145 : {
2146 0 : Error error (tok->get_locus (),
2147 : "C-style string literals require "
2148 : "%<-frust-c-style-string-literals%> to be enabled");
2149 0 : add_error (std::move (error));
2150 : return tl::unexpected<Parse::Error::Expr> (
2151 0 : Parse::Error::Expr::MALFORMED);
2152 0 : }
2153 11747 : case CHAR_LITERAL:
2154 11747 : return std::unique_ptr<AST::LiteralExpr> (
2155 46988 : new AST::LiteralExpr (tok->get_str (), AST::Literal::CHAR,
2156 11747 : tok->get_type_hint (), {}, tok->get_locus ()));
2157 135 : case BYTE_CHAR_LITERAL:
2158 135 : return std::unique_ptr<AST::LiteralExpr> (
2159 540 : new AST::LiteralExpr (tok->get_str (), AST::Literal::BYTE,
2160 135 : tok->get_type_hint (), {}, tok->get_locus ()));
2161 898 : case TRUE_LITERAL:
2162 898 : return std::unique_ptr<AST::LiteralExpr> (
2163 2694 : new AST::LiteralExpr (Values::Keywords::TRUE_LITERAL,
2164 : AST::Literal::BOOL, tok->get_type_hint (), {},
2165 898 : tok->get_locus ()));
2166 768 : case FALSE_LITERAL:
2167 768 : return std::unique_ptr<AST::LiteralExpr> (
2168 2304 : new AST::LiteralExpr (Values::Keywords::FALSE_LITERAL,
2169 : AST::Literal::BOOL, tok->get_type_hint (), {},
2170 768 : tok->get_locus ()));
2171 12597 : case LEFT_PAREN:
2172 : {
2173 12597 : auto grouped_or_tuple_expr
2174 12597 : = parse_grouped_or_tuple_expr (std::move (outer_attrs),
2175 : tok->get_locus ());
2176 12597 : if (grouped_or_tuple_expr)
2177 12596 : return std::move (grouped_or_tuple_expr.value ());
2178 : else
2179 : return tl::unexpected<Parse::Error::Expr> (
2180 1 : Parse::Error::Expr::CHILD_ERROR);
2181 12597 : }
2182 :
2183 : /*case PLUS: { // unary plus operator
2184 : // invoke parse_expr recursively with appropriate priority, etc. for
2185 : below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
2186 :
2187 : if (expr == nullptr)
2188 : return nullptr;
2189 : // can only apply to integer and float expressions
2190 : if (expr->get_type() != integer_type_node || expr->get_type() !=
2191 : float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
2192 : plus must be int or float but it is %s", print_type(expr->get_type()));
2193 : return nullptr;
2194 : }
2195 :
2196 : return Tree(expr, tok->get_locus());
2197 : }*/
2198 : // Rust has no unary plus operator
2199 3563 : case MINUS:
2200 : { // unary minus
2201 3563 : ParseRestrictions entered_from_unary;
2202 3563 : entered_from_unary.entered_from_unary = true;
2203 3563 : if (!restrictions.can_be_struct_expr)
2204 15 : entered_from_unary.can_be_struct_expr = false;
2205 3563 : auto expr = parse_expr (LBP_UNARY_MINUS, {}, entered_from_unary);
2206 :
2207 3563 : if (!expr)
2208 : return tl::unexpected<Parse::Error::Expr> (
2209 0 : Parse::Error::Expr::CHILD_ERROR);
2210 : // can only apply to integer and float expressions
2211 : /*if (expr.get_type() != integer_type_node || expr.get_type() !=
2212 : float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
2213 : minus must be int or float but it is %s",
2214 : print_type(expr.get_type())); return Tree::error();
2215 : }*/
2216 : /* FIXME: when implemented the "get type" method on expr, ensure it is
2217 : * int or float type (except unsigned int). Actually, this would
2218 : * probably have to be done in semantic analysis (as type checking).
2219 : */
2220 :
2221 : /* FIXME: allow outer attributes on these expressions by having an
2222 : * outer attrs parameter in function*/
2223 3563 : return std::make_unique<AST::NegationExpr> (std::move (expr.value ()),
2224 3563 : NegationOperator::NEGATE,
2225 : std::move (outer_attrs),
2226 7126 : tok->get_locus ());
2227 3563 : }
2228 665 : case EXCLAM:
2229 : { // logical or bitwise not
2230 665 : ParseRestrictions entered_from_unary;
2231 665 : entered_from_unary.entered_from_unary = true;
2232 665 : if (!restrictions.can_be_struct_expr)
2233 159 : entered_from_unary.can_be_struct_expr = false;
2234 665 : auto expr = parse_expr (LBP_UNARY_EXCLAM, {}, entered_from_unary);
2235 :
2236 665 : if (!expr)
2237 : return tl::unexpected<Parse::Error::Expr> (
2238 0 : Parse::Error::Expr::CHILD_ERROR);
2239 : // can only apply to boolean expressions
2240 : /*if (expr.get_type() != boolean_type_node) {
2241 : rust_error_at(tok->get_locus(),
2242 : "operand of logical not must be a boolean but it is %s",
2243 : print_type(expr.get_type()));
2244 : return Tree::error();
2245 : }*/
2246 : /* FIXME: type checking for boolean or integer expressions in semantic
2247 : * analysis */
2248 :
2249 : // FIXME: allow outer attributes on these expressions
2250 665 : return std::make_unique<AST::NegationExpr> (std::move (expr.value ()),
2251 665 : NegationOperator::NOT,
2252 : std::move (outer_attrs),
2253 1330 : tok->get_locus ());
2254 665 : }
2255 9341 : case ASTERISK:
2256 : {
2257 : /* pointer dereference only - HACK: as struct expressions should
2258 : * always be value expressions, cannot be dereferenced */
2259 9341 : ParseRestrictions entered_from_unary;
2260 9341 : entered_from_unary.entered_from_unary = true;
2261 9341 : entered_from_unary.can_be_struct_expr = false;
2262 9341 : auto expr = parse_expr (LBP_UNARY_ASTERISK, {}, entered_from_unary);
2263 9341 : if (!expr)
2264 : return tl::unexpected<Parse::Error::Expr> (
2265 1 : Parse::Error::Expr::CHILD_ERROR);
2266 : // FIXME: allow outer attributes on expression
2267 9340 : return std::make_unique<AST::DereferenceExpr> (std::move (
2268 9340 : expr.value ()),
2269 : std::move (outer_attrs),
2270 18680 : tok->get_locus ());
2271 9341 : }
2272 3591 : case AMP:
2273 : {
2274 : // (single) "borrow" expression - shared (mutable) or immutable
2275 3591 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr> expr
2276 : = tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
2277 3591 : Mutability mutability = Mutability::Imm;
2278 : bool raw_borrow = false;
2279 :
2280 3591 : ParseRestrictions entered_from_unary;
2281 3591 : entered_from_unary.entered_from_unary = true;
2282 3591 : if (!restrictions.can_be_struct_expr)
2283 14 : entered_from_unary.can_be_struct_expr = false;
2284 :
2285 9 : auto is_mutability = [] (const_TokenPtr token) {
2286 9 : return token->get_id () == CONST || token->get_id () == MUT;
2287 : };
2288 :
2289 3591 : auto t = lexer.peek_token ();
2290 : // Weak raw keyword, we look (1) ahead and treat it as an identifier if
2291 : // there is no mut nor const.
2292 6071 : if (t->get_id () == IDENTIFIER
2293 1657 : && t->get_str () == Values::WeakKeywords::RAW
2294 4728 : && is_mutability (lexer.peek_token (1)))
2295 : {
2296 7 : lexer.skip_token ();
2297 14 : switch (lexer.peek_token ()->get_id ())
2298 : {
2299 6 : case MUT:
2300 6 : mutability = Mutability::Mut;
2301 6 : break;
2302 : case CONST:
2303 : mutability = Mutability::Imm;
2304 : break;
2305 0 : default:
2306 0 : rust_error_at (lexer.peek_token ()->get_locus (),
2307 : "raw borrow should be either const or mut");
2308 : }
2309 7 : lexer.skip_token ();
2310 7 : auto expr_result
2311 7 : = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary);
2312 7 : if (expr_result)
2313 7 : expr = std::move (expr_result.value ());
2314 : else
2315 : return tl::unexpected<Parse::Error::Expr> (
2316 0 : Parse::Error::Expr::CHILD_ERROR);
2317 7 : raw_borrow = true;
2318 7 : }
2319 3584 : else if (t->get_id () == MUT)
2320 : {
2321 858 : lexer.skip_token ();
2322 858 : auto expr_result
2323 858 : = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary);
2324 858 : if (expr_result)
2325 858 : expr = std::move (expr_result.value ());
2326 : else
2327 : return tl::unexpected<Parse::Error::Expr> (
2328 0 : Parse::Error::Expr::CHILD_ERROR);
2329 858 : mutability = Mutability::Mut;
2330 858 : raw_borrow = false;
2331 858 : }
2332 : else
2333 : {
2334 2726 : auto expr_result
2335 2726 : = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary);
2336 2726 : if (expr_result)
2337 2725 : expr = std::move (expr_result.value ());
2338 : else
2339 : return tl::unexpected<Parse::Error::Expr> (
2340 1 : Parse::Error::Expr::CHILD_ERROR);
2341 2725 : raw_borrow = false;
2342 2726 : }
2343 :
2344 : // FIXME: allow outer attributes on expression
2345 3590 : return std::make_unique<AST::BorrowExpr> (std::move (expr.value ()),
2346 3590 : mutability, raw_borrow, false,
2347 : std::move (outer_attrs),
2348 7180 : tok->get_locus ());
2349 7181 : }
2350 38 : case LOGICAL_AND:
2351 : {
2352 : // (double) "borrow" expression - shared (mutable) or immutable
2353 38 : std::unique_ptr<AST::Expr> expr = nullptr;
2354 38 : Mutability mutability = Mutability::Imm;
2355 :
2356 38 : ParseRestrictions entered_from_unary;
2357 38 : entered_from_unary.entered_from_unary = true;
2358 :
2359 76 : if (lexer.peek_token ()->get_id () == MUT)
2360 : {
2361 0 : lexer.skip_token ();
2362 0 : auto expr_res
2363 0 : = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary);
2364 0 : if (!expr_res)
2365 : return tl::unexpected<Parse::Error::Expr> (
2366 0 : Parse::Error::Expr::CHILD_ERROR);
2367 0 : expr = std::move (expr_res.value ());
2368 0 : mutability = Mutability::Mut;
2369 0 : }
2370 : else
2371 : {
2372 38 : auto expr_result
2373 38 : = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary);
2374 38 : if (expr_result)
2375 38 : expr = std::move (expr_result.value ());
2376 : else
2377 : return tl::unexpected<Parse::Error::Expr> (
2378 0 : Parse::Error::Expr::CHILD_ERROR);
2379 38 : mutability = Mutability::Imm;
2380 38 : }
2381 :
2382 : // FIXME: allow outer attributes on expression
2383 38 : return std::make_unique<AST::BorrowExpr> (std::move (expr), mutability,
2384 38 : false, true,
2385 : std::move (outer_attrs),
2386 38 : tok->get_locus ());
2387 38 : }
2388 382 : case OR:
2389 : case PIPE:
2390 : case MOVE:
2391 : // closure expression
2392 : {
2393 1146 : auto ret = parse_closure_expr_pratt (tok, std::move (outer_attrs));
2394 382 : if (ret)
2395 382 : return std::move (ret.value ());
2396 : else
2397 : return tl::unexpected<Parse::Error::Expr> (
2398 0 : Parse::Error::Expr::CHILD_ERROR);
2399 382 : }
2400 173 : case DOT_DOT:
2401 : // either "range to" or "range full" expressions
2402 : {
2403 173 : auto ret
2404 519 : = parse_nud_range_exclusive_expr (tok, std::move (outer_attrs));
2405 173 : if (ret)
2406 173 : return std::move (ret.value ());
2407 : else
2408 : return tl::unexpected<Parse::Error::Expr> (
2409 0 : Parse::Error::Expr::CHILD_ERROR);
2410 173 : }
2411 0 : case DOT_DOT_EQ:
2412 : // range to inclusive expr
2413 : {
2414 0 : auto ret = parse_range_to_inclusive_expr (tok, std::move (outer_attrs));
2415 0 : if (ret)
2416 0 : return std::move (ret.value ());
2417 : else
2418 : return tl::unexpected<Parse::Error::Expr> (
2419 0 : Parse::Error::Expr::CHILD_ERROR);
2420 0 : }
2421 932 : case RETURN_KW:
2422 : // FIXME: is this really a null denotation expression?
2423 : {
2424 932 : auto ret
2425 932 : = parse_return_expr (std::move (outer_attrs), tok->get_locus ());
2426 932 : if (ret)
2427 932 : return std::move (ret.value ());
2428 : else
2429 : return tl::unexpected<Parse::Error::Expr> (
2430 0 : Parse::Error::Expr::CHILD_ERROR);
2431 932 : }
2432 31 : case TRY:
2433 : // FIXME: is this really a null denotation expression?
2434 : {
2435 31 : auto ret = parse_try_expr (std::move (outer_attrs), tok->get_locus ());
2436 31 : if (ret)
2437 31 : return std::move (ret.value ());
2438 : else
2439 : return tl::unexpected<Parse::Error::Expr> (
2440 0 : Parse::Error::Expr::CHILD_ERROR);
2441 31 : }
2442 127 : case BREAK:
2443 : // FIXME: is this really a null denotation expression?
2444 : {
2445 127 : auto ret
2446 127 : = parse_break_expr (std::move (outer_attrs), tok->get_locus ());
2447 127 : if (ret)
2448 127 : return std::move (ret.value ());
2449 : else
2450 : return tl::unexpected<Parse::Error::Expr> (
2451 0 : Parse::Error::Expr::CHILD_ERROR);
2452 127 : }
2453 40 : case CONTINUE:
2454 40 : return parse_continue_expr (std::move (outer_attrs), tok->get_locus ());
2455 2645 : case LEFT_CURLY:
2456 : // ok - this is an expression with block for once.
2457 : {
2458 2645 : auto ret = parse_block_expr (std::move (outer_attrs), tl::nullopt,
2459 : tok->get_locus ());
2460 2645 : if (ret)
2461 2644 : return std::move (ret.value ());
2462 : else
2463 : return tl::unexpected<Parse::Error::Expr> (
2464 1 : Parse::Error::Expr::CHILD_ERROR);
2465 2645 : }
2466 3978 : case IF:
2467 : // if or if let, so more lookahead to find out
2468 7956 : if (lexer.peek_token ()->get_id () == LET)
2469 : {
2470 : // if let expr
2471 120 : auto ret
2472 120 : = parse_if_let_expr (std::move (outer_attrs), tok->get_locus ());
2473 120 : if (ret)
2474 120 : return std::move (ret.value ());
2475 : else
2476 : return tl::unexpected<Parse::Error::Expr> (
2477 0 : Parse::Error::Expr::CHILD_ERROR);
2478 120 : }
2479 : else
2480 : {
2481 : // if expr
2482 3858 : auto ret = parse_if_expr (std::move (outer_attrs), tok->get_locus ());
2483 3858 : if (ret)
2484 3857 : return std::move (ret.value ());
2485 : else
2486 : return tl::unexpected<Parse::Error::Expr> (
2487 1 : Parse::Error::Expr::CHILD_ERROR);
2488 3858 : }
2489 60 : case LIFETIME:
2490 : {
2491 180 : auto ret = parse_labelled_loop_expr (tok, std::move (outer_attrs));
2492 60 : if (ret)
2493 60 : return std::move (ret.value ());
2494 : else
2495 : return tl::unexpected<Parse::Error::Expr> (
2496 0 : Parse::Error::Expr::CHILD_ERROR);
2497 60 : }
2498 116 : case LOOP:
2499 : {
2500 116 : auto ret = parse_loop_expr (std::move (outer_attrs), tl::nullopt,
2501 : tok->get_locus ());
2502 116 : if (ret)
2503 115 : return std::move (ret.value ());
2504 : else
2505 : return tl::unexpected<Parse::Error::Expr> (
2506 1 : Parse::Error::Expr::CHILD_ERROR);
2507 116 : }
2508 209 : case WHILE:
2509 418 : if (lexer.peek_token ()->get_id () == LET)
2510 : {
2511 29 : auto ret = parse_while_let_loop_expr (std::move (outer_attrs));
2512 29 : if (ret)
2513 28 : return std::move (ret.value ());
2514 : else
2515 : return tl::unexpected<Parse::Error::Expr> (
2516 1 : Parse::Error::Expr::CHILD_ERROR);
2517 29 : }
2518 : else
2519 : {
2520 180 : auto ret = parse_while_loop_expr (std::move (outer_attrs),
2521 360 : tl::nullopt, tok->get_locus ());
2522 180 : if (ret)
2523 180 : return std::move (ret.value ());
2524 : else
2525 : return tl::unexpected<Parse::Error::Expr> (
2526 0 : Parse::Error::Expr::CHILD_ERROR);
2527 180 : }
2528 222 : case FOR:
2529 : {
2530 222 : auto ret = parse_for_loop_expr (std::move (outer_attrs), tl::nullopt);
2531 222 : if (ret)
2532 222 : return std::move (ret.value ());
2533 : else
2534 : return tl::unexpected<Parse::Error::Expr> (
2535 0 : Parse::Error::Expr::CHILD_ERROR);
2536 222 : }
2537 5568 : case MATCH_KW:
2538 : // also an expression with block
2539 : {
2540 5568 : auto ret
2541 5568 : = parse_match_expr (std::move (outer_attrs), tok->get_locus ());
2542 5568 : if (ret)
2543 5564 : return std::move (ret.value ());
2544 : else
2545 : return tl::unexpected<Parse::Error::Expr> (
2546 4 : Parse::Error::Expr::CHILD_ERROR);
2547 5568 : }
2548 :
2549 13213 : case LEFT_SQUARE:
2550 : // array definition expr (not indexing)
2551 : {
2552 13213 : auto ret
2553 13213 : = parse_array_expr (std::move (outer_attrs), tok->get_locus ());
2554 13213 : if (ret)
2555 13213 : return std::move (ret.value ());
2556 : else
2557 : return tl::unexpected<Parse::Error::Expr> (
2558 0 : Parse::Error::Expr::CHILD_ERROR);
2559 13213 : }
2560 4817 : case UNSAFE:
2561 : {
2562 4817 : auto ret = parse_unsafe_block_expr (std::move (outer_attrs),
2563 : tok->get_locus ());
2564 4817 : if (ret)
2565 4817 : return std::move (ret.value ());
2566 : else
2567 : return tl::unexpected<Parse::Error::Expr> (
2568 0 : Parse::Error::Expr::CHILD_ERROR);
2569 4817 : }
2570 5 : case BOX:
2571 : {
2572 5 : auto ret = parse_box_expr (std::move (outer_attrs), tok->get_locus ());
2573 5 : if (ret)
2574 5 : return std::move (ret.value ());
2575 : else
2576 : return tl::unexpected<Parse::Error::Expr> (
2577 0 : Parse::Error::Expr::CHILD_ERROR);
2578 5 : }
2579 1 : case UNDERSCORE:
2580 1 : add_error (
2581 1 : Error (tok->get_locus (),
2582 : "use of %qs is not allowed on the right-side of an assignment",
2583 : tok->get_token_description ()));
2584 1 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
2585 15 : case CONST:
2586 : {
2587 15 : auto ret
2588 15 : = parse_const_block_expr (std::move (outer_attrs), tok->get_locus ());
2589 15 : if (ret)
2590 15 : return std::move (ret.value ());
2591 : else
2592 : return tl::unexpected<Parse::Error::Expr> (
2593 0 : Parse::Error::Expr::CHILD_ERROR);
2594 15 : }
2595 49 : default:
2596 49 : if (!restrictions.expr_can_be_null)
2597 49 : add_error (Error (tok->get_locus (),
2598 : "found unexpected token %qs in null denotation",
2599 : tok->get_token_description ()));
2600 49 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
2601 : }
2602 : }
2603 :
2604 : /* Called for each token that can appear in infix (between) position. Can be
2605 : * operators or other punctuation. Returns a function pointer to member
2606 : * function that implements the left denotation for the token given. */
2607 : template <typename ManagedTokenSource>
2608 : tl::expected<std::unique_ptr<AST::Expr>, Parse::Error::Expr>
2609 98372 : Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
2610 : std::unique_ptr<AST::Expr> left,
2611 : AST::AttrVec outer_attrs,
2612 : ParseRestrictions restrictions)
2613 : {
2614 : // Token passed in has already been skipped, so peek gives "next" token
2615 98372 : switch (tok->get_id ())
2616 : {
2617 : // FIXME: allow for outer attributes to be applied
2618 203 : case QUESTION_MARK:
2619 : {
2620 203 : location_t left_locus = left->get_locus ();
2621 : // error propagation expression - unary postfix
2622 203 : return std::make_unique<AST::ErrorPropagationExpr> (
2623 203 : std::move (left), std::move (outer_attrs), left_locus);
2624 : }
2625 11211 : case PLUS:
2626 : // sum expression - binary infix
2627 : /*return parse_binary_plus_expr (tok, std::move (left),
2628 : std::move (outer_attrs), restrictions);*/
2629 44844 : return parse_arithmetic_or_logical_expr (tok, std::move (left),
2630 : std::move (outer_attrs),
2631 : ArithmeticOrLogicalOperator::ADD,
2632 11211 : restrictions);
2633 3432 : case MINUS:
2634 : // difference expression - binary infix
2635 : /*return parse_binary_minus_expr (tok, std::move (left),
2636 : std::move (outer_attrs),
2637 : restrictions);*/
2638 13728 : return parse_arithmetic_or_logical_expr (
2639 : tok, std::move (left), std::move (outer_attrs),
2640 3432 : ArithmeticOrLogicalOperator::SUBTRACT, restrictions);
2641 444 : case ASTERISK:
2642 : // product expression - binary infix
2643 : /*return parse_binary_mult_expr (tok, std::move (left),
2644 : std::move (outer_attrs), restrictions);*/
2645 1776 : return parse_arithmetic_or_logical_expr (
2646 : tok, std::move (left), std::move (outer_attrs),
2647 444 : ArithmeticOrLogicalOperator::MULTIPLY, restrictions);
2648 220 : case DIV:
2649 : // quotient expression - binary infix
2650 : /*return parse_binary_div_expr (tok, std::move (left),
2651 : std::move (outer_attrs), restrictions);*/
2652 880 : return parse_arithmetic_or_logical_expr (
2653 : tok, std::move (left), std::move (outer_attrs),
2654 220 : ArithmeticOrLogicalOperator::DIVIDE, restrictions);
2655 207 : case PERCENT:
2656 : // modulo expression - binary infix
2657 : /*return parse_binary_mod_expr (tok, std::move (left),
2658 : std::move (outer_attrs), restrictions);*/
2659 828 : return parse_arithmetic_or_logical_expr (
2660 : tok, std::move (left), std::move (outer_attrs),
2661 207 : ArithmeticOrLogicalOperator::MODULUS, restrictions);
2662 4341 : case AMP:
2663 : // logical or bitwise and expression - binary infix
2664 : /*return parse_bitwise_and_expr (tok, std::move (left),
2665 : std::move (outer_attrs), restrictions);*/
2666 17364 : return parse_arithmetic_or_logical_expr (
2667 : tok, std::move (left), std::move (outer_attrs),
2668 4341 : ArithmeticOrLogicalOperator::BITWISE_AND, restrictions);
2669 1732 : case PIPE:
2670 : // logical or bitwise or expression - binary infix
2671 : /*return parse_bitwise_or_expr (tok, std::move (left),
2672 : std::move (outer_attrs), restrictions);*/
2673 6928 : return parse_arithmetic_or_logical_expr (
2674 : tok, std::move (left), std::move (outer_attrs),
2675 1732 : ArithmeticOrLogicalOperator::BITWISE_OR, restrictions);
2676 125 : case CARET:
2677 : // logical or bitwise xor expression - binary infix
2678 : /*return parse_bitwise_xor_expr (tok, std::move (left),
2679 : std::move (outer_attrs), restrictions);*/
2680 500 : return parse_arithmetic_or_logical_expr (
2681 : tok, std::move (left), std::move (outer_attrs),
2682 125 : ArithmeticOrLogicalOperator::BITWISE_XOR, restrictions);
2683 2497 : case LEFT_SHIFT:
2684 : // left shift expression - binary infix
2685 : /*return parse_left_shift_expr (tok, std::move (left),
2686 : std::move (outer_attrs), restrictions);*/
2687 9988 : return parse_arithmetic_or_logical_expr (
2688 : tok, std::move (left), std::move (outer_attrs),
2689 2497 : ArithmeticOrLogicalOperator::LEFT_SHIFT, restrictions);
2690 3845 : case RIGHT_SHIFT:
2691 : // right shift expression - binary infix
2692 : /*return parse_right_shift_expr (tok, std::move (left),
2693 : std::move (outer_attrs), restrictions);*/
2694 15380 : return parse_arithmetic_or_logical_expr (
2695 : tok, std::move (left), std::move (outer_attrs),
2696 3845 : ArithmeticOrLogicalOperator::RIGHT_SHIFT, restrictions);
2697 1608 : case EQUAL_EQUAL:
2698 : // equal to expression - binary infix (no associativity)
2699 : /*return parse_binary_equal_expr (tok, std::move (left),
2700 : std::move (outer_attrs),
2701 : restrictions);*/
2702 6432 : return parse_comparison_expr (tok, std::move (left),
2703 : std::move (outer_attrs),
2704 1608 : ComparisonOperator::EQUAL, restrictions);
2705 1505 : case NOT_EQUAL:
2706 : // not equal to expression - binary infix (no associativity)
2707 : /*return parse_binary_not_equal_expr (tok, std::move (left),
2708 : std::move (outer_attrs),
2709 : restrictions);*/
2710 6020 : return parse_comparison_expr (tok, std::move (left),
2711 : std::move (outer_attrs),
2712 : ComparisonOperator::NOT_EQUAL,
2713 1505 : restrictions);
2714 974 : case RIGHT_ANGLE:
2715 : // greater than expression - binary infix (no associativity)
2716 : /*return parse_binary_greater_than_expr (tok, std::move (left),
2717 : std::move (outer_attrs),
2718 : restrictions);*/
2719 3896 : return parse_comparison_expr (tok, std::move (left),
2720 : std::move (outer_attrs),
2721 : ComparisonOperator::GREATER_THAN,
2722 974 : restrictions);
2723 936 : case LEFT_ANGLE:
2724 : // less than expression - binary infix (no associativity)
2725 : /*return parse_binary_less_than_expr (tok, std::move (left),
2726 : std::move (outer_attrs),
2727 : restrictions);*/
2728 3744 : return parse_comparison_expr (tok, std::move (left),
2729 : std::move (outer_attrs),
2730 : ComparisonOperator::LESS_THAN,
2731 936 : restrictions);
2732 448 : case GREATER_OR_EQUAL:
2733 : // greater than or equal to expression - binary infix (no associativity)
2734 : /*return parse_binary_greater_equal_expr (tok, std::move (left),
2735 : std::move (outer_attrs),
2736 : restrictions);*/
2737 1792 : return parse_comparison_expr (tok, std::move (left),
2738 : std::move (outer_attrs),
2739 : ComparisonOperator::GREATER_OR_EQUAL,
2740 448 : restrictions);
2741 385 : case LESS_OR_EQUAL:
2742 : // less than or equal to expression - binary infix (no associativity)
2743 : /*return parse_binary_less_equal_expr (tok, std::move (left),
2744 : std::move (outer_attrs),
2745 : restrictions);*/
2746 1540 : return parse_comparison_expr (tok, std::move (left),
2747 : std::move (outer_attrs),
2748 : ComparisonOperator::LESS_OR_EQUAL,
2749 385 : restrictions);
2750 264 : case OR:
2751 : // lazy logical or expression - binary infix
2752 1056 : return parse_lazy_or_expr (tok, std::move (left), std::move (outer_attrs),
2753 264 : restrictions);
2754 580 : case LOGICAL_AND:
2755 : // lazy logical and expression - binary infix
2756 2320 : return parse_lazy_and_expr (tok, std::move (left),
2757 580 : std::move (outer_attrs), restrictions);
2758 9146 : case AS:
2759 : /* type cast expression - kind of binary infix (RHS is actually a
2760 : * TypeNoBounds) */
2761 36584 : return parse_type_cast_expr (tok, std::move (left),
2762 9146 : std::move (outer_attrs), restrictions);
2763 3634 : case EQUAL:
2764 : // assignment expression - binary infix (note right-to-left
2765 : // associativity)
2766 14536 : return parse_assig_expr (tok, std::move (left), std::move (outer_attrs),
2767 3634 : restrictions);
2768 348 : case PLUS_EQ:
2769 : /* plus-assignment expression - binary infix (note right-to-left
2770 : * associativity) */
2771 : /*return parse_plus_assig_expr (tok, std::move (left),
2772 : std::move (outer_attrs), restrictions);*/
2773 1392 : return parse_compound_assignment_expr (tok, std::move (left),
2774 : std::move (outer_attrs),
2775 : CompoundAssignmentOperator::ADD,
2776 348 : restrictions);
2777 217 : case MINUS_EQ:
2778 : /* minus-assignment expression - binary infix (note right-to-left
2779 : * associativity) */
2780 : /*return parse_minus_assig_expr (tok, std::move (left),
2781 : std::move (outer_attrs), restrictions);*/
2782 868 : return parse_compound_assignment_expr (
2783 : tok, std::move (left), std::move (outer_attrs),
2784 217 : CompoundAssignmentOperator::SUBTRACT, restrictions);
2785 28 : case ASTERISK_EQ:
2786 : /* multiply-assignment expression - binary infix (note right-to-left
2787 : * associativity) */
2788 : /*return parse_mult_assig_expr (tok, std::move (left),
2789 : std::move (outer_attrs), restrictions);*/
2790 112 : return parse_compound_assignment_expr (
2791 : tok, std::move (left), std::move (outer_attrs),
2792 28 : CompoundAssignmentOperator::MULTIPLY, restrictions);
2793 92 : case DIV_EQ:
2794 : /* division-assignment expression - binary infix (note right-to-left
2795 : * associativity) */
2796 : /*return parse_div_assig_expr (tok, std::move (left),
2797 : std::move (outer_attrs), restrictions);*/
2798 368 : return parse_compound_assignment_expr (tok, std::move (left),
2799 : std::move (outer_attrs),
2800 : CompoundAssignmentOperator::DIVIDE,
2801 92 : restrictions);
2802 22 : case PERCENT_EQ:
2803 : /* modulo-assignment expression - binary infix (note right-to-left
2804 : * associativity) */
2805 : /*return parse_mod_assig_expr (tok, std::move (left),
2806 : std::move (outer_attrs), restrictions);*/
2807 88 : return parse_compound_assignment_expr (
2808 : tok, std::move (left), std::move (outer_attrs),
2809 22 : CompoundAssignmentOperator::MODULUS, restrictions);
2810 34 : case AMP_EQ:
2811 : /* bitwise and-assignment expression - binary infix (note right-to-left
2812 : * associativity) */
2813 : /*return parse_and_assig_expr (tok, std::move (left),
2814 : std::move (outer_attrs), restrictions);*/
2815 136 : return parse_compound_assignment_expr (
2816 : tok, std::move (left), std::move (outer_attrs),
2817 34 : CompoundAssignmentOperator::BITWISE_AND, restrictions);
2818 86 : case PIPE_EQ:
2819 : /* bitwise or-assignment expression - binary infix (note right-to-left
2820 : * associativity) */
2821 : /*return parse_or_assig_expr (tok, std::move (left),
2822 : std::move (outer_attrs), restrictions);*/
2823 344 : return parse_compound_assignment_expr (
2824 : tok, std::move (left), std::move (outer_attrs),
2825 86 : CompoundAssignmentOperator::BITWISE_OR, restrictions);
2826 403 : case CARET_EQ:
2827 : /* bitwise xor-assignment expression - binary infix (note right-to-left
2828 : * associativity) */
2829 : /*return parse_xor_assig_expr (tok, std::move (left),
2830 : std::move (outer_attrs), restrictions);*/
2831 1612 : return parse_compound_assignment_expr (
2832 : tok, std::move (left), std::move (outer_attrs),
2833 403 : CompoundAssignmentOperator::BITWISE_XOR, restrictions);
2834 159 : case LEFT_SHIFT_EQ:
2835 : /* left shift-assignment expression - binary infix (note right-to-left
2836 : * associativity) */
2837 : /*return parse_left_shift_assig_expr (tok, std::move (left),
2838 : std::move (outer_attrs),
2839 : restrictions);*/
2840 636 : return parse_compound_assignment_expr (
2841 : tok, std::move (left), std::move (outer_attrs),
2842 159 : CompoundAssignmentOperator::LEFT_SHIFT, restrictions);
2843 155 : case RIGHT_SHIFT_EQ:
2844 : /* right shift-assignment expression - binary infix (note right-to-left
2845 : * associativity) */
2846 : /*return parse_right_shift_assig_expr (tok, std::move (left),
2847 : std::move (outer_attrs),
2848 : restrictions);*/
2849 620 : return parse_compound_assignment_expr (
2850 : tok, std::move (left), std::move (outer_attrs),
2851 155 : CompoundAssignmentOperator::RIGHT_SHIFT, restrictions);
2852 362 : case DOT_DOT:
2853 : /* range exclusive expression - binary infix (no associativity)
2854 : * either "range" or "range from" */
2855 1448 : return parse_led_range_exclusive_expr (tok, std::move (left),
2856 : std::move (outer_attrs),
2857 362 : restrictions);
2858 13 : case DOT_DOT_EQ:
2859 : /* range inclusive expression - binary infix (no associativity)
2860 : * unambiguously RangeInclusiveExpr */
2861 52 : return parse_range_inclusive_expr (tok, std::move (left),
2862 13 : std::move (outer_attrs), restrictions);
2863 0 : case SCOPE_RESOLUTION:
2864 : // path expression - binary infix? FIXME should this even be parsed
2865 : // here?
2866 0 : add_error (
2867 0 : Error (tok->get_locus (),
2868 : "found scope resolution operator in left denotation "
2869 : "function - this should probably be handled elsewhere"));
2870 :
2871 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
2872 46582 : case DOT:
2873 : {
2874 : /* field expression or method call - relies on parentheses after next
2875 : * identifier or await if token after is "await" (unary postfix) or
2876 : * tuple index if token after is a decimal int literal */
2877 :
2878 46582 : const_TokenPtr next_tok = lexer.peek_token ();
2879 46582 : if (next_tok->get_id () == IDENTIFIER
2880 46582 : && next_tok->get_str () == Values::Keywords::AWAIT)
2881 : {
2882 : // await expression
2883 0 : return parse_await_expr (tok, std::move (left),
2884 0 : std::move (outer_attrs));
2885 : }
2886 46582 : else if (next_tok->get_id () == INT_LITERAL)
2887 : {
2888 : // tuple index expression - TODO check for decimal int literal
2889 35792 : return parse_tuple_index_expr (tok, std::move (left),
2890 : std::move (outer_attrs),
2891 8948 : restrictions);
2892 : }
2893 37634 : else if (next_tok->get_id () == FLOAT_LITERAL)
2894 : {
2895 : // Lexer has misidentified a tuple index as a float literal
2896 : // eg: `(x, (y, z)).1.0` -> 1.0 has been identified as a float
2897 : // literal. This means we should split it into three new separate
2898 : // tokens, the first tuple index, the dot and the second tuple
2899 : // index.
2900 2 : auto current_loc = next_tok->get_locus ();
2901 2 : auto str = next_tok->get_str ();
2902 2 : auto dot_pos = str.find (".");
2903 2 : auto prefix = str.substr (0, dot_pos);
2904 2 : auto suffix = str.substr (dot_pos + 1);
2905 2 : if (dot_pos == str.size () - 1)
2906 : {
2907 1 : auto prefix_len = prefix.length ();
2908 3 : lexer.split_current_token (
2909 2 : {Token::make_int (current_loc, std::move (prefix), prefix_len,
2910 : IntegerLiteralBase::Decimal,
2911 : CORETYPE_PURE_DECIMAL),
2912 : Token::make (DOT, current_loc + 1)});
2913 : }
2914 : else
2915 : {
2916 1 : auto prefix_len = prefix.length ();
2917 1 : auto suffix_len = suffix.length ();
2918 5 : lexer.split_current_token (
2919 2 : {Token::make_int (current_loc, std::move (prefix), prefix_len,
2920 : IntegerLiteralBase::Decimal,
2921 : CORETYPE_PURE_DECIMAL),
2922 : Token::make (DOT, current_loc + 1),
2923 2 : Token::make_int (current_loc + 2, std::move (suffix),
2924 : suffix_len, IntegerLiteralBase::Decimal,
2925 : CORETYPE_PURE_DECIMAL)});
2926 : }
2927 8 : return parse_tuple_index_expr (tok, std::move (left),
2928 : std::move (outer_attrs),
2929 2 : restrictions);
2930 2 : }
2931 49333 : else if (next_tok->get_id () == IDENTIFIER
2932 79852 : && lexer.peek_token (1)->get_id () != LEFT_PAREN
2933 76080 : && lexer.peek_token (1)->get_id () != SCOPE_RESOLUTION)
2934 : {
2935 : /* field expression (or should be) - FIXME: scope resolution right
2936 : * after identifier should always be method, I'm pretty sure */
2937 31508 : return parse_field_access_expr (tok, std::move (left),
2938 : std::move (outer_attrs),
2939 7877 : restrictions);
2940 : }
2941 : else
2942 : {
2943 : // method call (probably)
2944 119020 : return parse_method_call_expr (tok, std::move (left),
2945 : std::move (outer_attrs),
2946 29755 : restrictions);
2947 : }
2948 46582 : }
2949 1269 : case LEFT_PAREN:
2950 : // function call - method call is based on dot notation first
2951 5076 : return parse_function_call_expr (tok, std::move (left),
2952 1269 : std::move (outer_attrs), restrictions);
2953 865 : case LEFT_SQUARE:
2954 : // array or slice index expression (pseudo binary infix)
2955 3460 : return parse_index_expr (tok, std::move (left), std::move (outer_attrs),
2956 865 : restrictions);
2957 0 : default:
2958 0 : add_error (Error (tok->get_locus (),
2959 : "found unexpected token %qs in left denotation",
2960 : tok->get_token_description ()));
2961 :
2962 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
2963 : }
2964 : }
2965 :
2966 : /* Returns the left binding power for the given ArithmeticOrLogicalExpr type.
2967 : * TODO make constexpr? Would that even do anything useful? */
2968 : inline binding_powers
2969 28054 : get_lbp_for_arithmetic_or_logical_expr (
2970 : AST::ArithmeticOrLogicalExpr::ExprType expr_type)
2971 : {
2972 28054 : switch (expr_type)
2973 : {
2974 : case ArithmeticOrLogicalOperator::ADD:
2975 : return LBP_PLUS;
2976 : case ArithmeticOrLogicalOperator::SUBTRACT:
2977 : return LBP_MINUS;
2978 : case ArithmeticOrLogicalOperator::MULTIPLY:
2979 : return LBP_MUL;
2980 : case ArithmeticOrLogicalOperator::DIVIDE:
2981 : return LBP_DIV;
2982 : case ArithmeticOrLogicalOperator::MODULUS:
2983 : return LBP_MOD;
2984 : case ArithmeticOrLogicalOperator::BITWISE_AND:
2985 : return LBP_AMP;
2986 : case ArithmeticOrLogicalOperator::BITWISE_OR:
2987 : return LBP_PIPE;
2988 : case ArithmeticOrLogicalOperator::BITWISE_XOR:
2989 : return LBP_CARET;
2990 : case ArithmeticOrLogicalOperator::LEFT_SHIFT:
2991 : return LBP_L_SHIFT;
2992 : case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
2993 : return LBP_R_SHIFT;
2994 0 : default:
2995 : // WTF? should not happen, this is an error
2996 0 : rust_unreachable ();
2997 :
2998 : return LBP_PLUS;
2999 : }
3000 : }
3001 :
3002 : // Parses an arithmetic or logical expression (with Pratt parsing).
3003 : template <typename ManagedTokenSource>
3004 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3005 28054 : Parser<ManagedTokenSource>::parse_arithmetic_or_logical_expr (
3006 : const_TokenPtr, std::unique_ptr<AST::Expr> left, AST::AttrVec,
3007 : AST::ArithmeticOrLogicalExpr::ExprType expr_type,
3008 : ParseRestrictions restrictions)
3009 : {
3010 : // parse RHS (as tok has already been consumed in parse_expression)
3011 28054 : auto right = parse_expr (get_lbp_for_arithmetic_or_logical_expr (expr_type),
3012 56108 : AST::AttrVec (), restrictions);
3013 28054 : if (!right)
3014 2 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3015 :
3016 : // TODO: check types. actually, do so during semantic analysis
3017 28052 : location_t locus = left->get_locus ();
3018 :
3019 28052 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3020 56104 : std::move (left), std::move (right.value ()), expr_type, locus);
3021 28054 : }
3022 :
3023 : // Parses a binary addition expression (with Pratt parsing).
3024 : template <typename ManagedTokenSource>
3025 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3026 0 : Parser<ManagedTokenSource>::parse_binary_plus_expr (
3027 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3028 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3029 : {
3030 : // parse RHS (as tok has already been consumed in parse_expression)
3031 0 : auto right = parse_expr (LBP_PLUS, AST::AttrVec (), restrictions);
3032 0 : if (!right)
3033 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3034 :
3035 : // TODO: check types. actually, do so during semantic analysis
3036 0 : location_t locus = left->get_locus ();
3037 :
3038 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3039 0 : std::move (left), std::move (right.value ()),
3040 0 : ArithmeticOrLogicalOperator::ADD, locus);
3041 0 : }
3042 :
3043 : // Parses a binary subtraction expression (with Pratt parsing).
3044 : template <typename ManagedTokenSource>
3045 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3046 0 : Parser<ManagedTokenSource>::parse_binary_minus_expr (
3047 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3048 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3049 : {
3050 : // parse RHS (as tok has already been consumed in parse_expression)
3051 0 : auto right = parse_expr (LBP_MINUS, AST::AttrVec (), restrictions);
3052 0 : if (!right)
3053 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3054 :
3055 : // TODO: check types. actually, do so during semantic analysis
3056 0 : location_t locus = left->get_locus ();
3057 :
3058 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3059 0 : std::move (left), std::move (right.value ()),
3060 0 : ArithmeticOrLogicalOperator::SUBTRACT, locus);
3061 0 : }
3062 :
3063 : // Parses a binary multiplication expression (with Pratt parsing).
3064 : template <typename ManagedTokenSource>
3065 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3066 0 : Parser<ManagedTokenSource>::parse_binary_mult_expr (
3067 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3068 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3069 : {
3070 : // parse RHS (as tok has already been consumed in parse_expression)
3071 0 : auto right = parse_expr (LBP_MUL, AST::AttrVec (), restrictions);
3072 0 : if (!right)
3073 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3074 :
3075 : // TODO: check types. actually, do so during semantic analysis
3076 0 : location_t locus = left->get_locus ();
3077 :
3078 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3079 0 : std::move (left), std::move (right.value ()),
3080 0 : ArithmeticOrLogicalOperator::MULTIPLY, locus);
3081 0 : }
3082 :
3083 : // Parses a binary division expression (with Pratt parsing).
3084 : template <typename ManagedTokenSource>
3085 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3086 0 : Parser<ManagedTokenSource>::parse_binary_div_expr (
3087 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3088 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3089 : {
3090 : // parse RHS (as tok has already been consumed in parse_expression)
3091 0 : auto right = parse_expr (LBP_DIV, AST::AttrVec (), restrictions);
3092 0 : if (!right)
3093 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3094 :
3095 : // TODO: check types. actually, do so during semantic analysis
3096 0 : location_t locus = left->get_locus ();
3097 :
3098 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3099 0 : std::move (left), std::move (right.value ()),
3100 0 : ArithmeticOrLogicalOperator::DIVIDE, locus);
3101 0 : }
3102 :
3103 : // Parses a binary modulo expression (with Pratt parsing).
3104 : template <typename ManagedTokenSource>
3105 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3106 0 : Parser<ManagedTokenSource>::parse_binary_mod_expr (
3107 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3108 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3109 : {
3110 : // parse RHS (as tok has already been consumed in parse_expression)
3111 0 : auto right = parse_expr (LBP_MOD, AST::AttrVec (), restrictions);
3112 0 : if (!right)
3113 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3114 :
3115 : // TODO: check types. actually, do so during semantic analysis
3116 0 : location_t locus = left->get_locus ();
3117 :
3118 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3119 0 : std::move (left), std::move (right.value ()),
3120 0 : ArithmeticOrLogicalOperator::MODULUS, locus);
3121 0 : }
3122 :
3123 : /* Parses a binary bitwise (or eager logical) and expression (with Pratt
3124 : * parsing). */
3125 : template <typename ManagedTokenSource>
3126 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3127 0 : Parser<ManagedTokenSource>::parse_bitwise_and_expr (
3128 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3129 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3130 : {
3131 : // parse RHS (as tok has already been consumed in parse_expression)
3132 0 : auto right = parse_expr (LBP_AMP, AST::AttrVec (), restrictions);
3133 0 : if (!right)
3134 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3135 :
3136 : // TODO: check types. actually, do so during semantic analysis
3137 0 : location_t locus = left->get_locus ();
3138 :
3139 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3140 0 : std::move (left), std::move (right.value ()),
3141 0 : ArithmeticOrLogicalOperator::BITWISE_AND, locus);
3142 0 : }
3143 :
3144 : /* Parses a binary bitwise (or eager logical) or expression (with Pratt
3145 : * parsing). */
3146 : template <typename ManagedTokenSource>
3147 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3148 0 : Parser<ManagedTokenSource>::parse_bitwise_or_expr (
3149 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3150 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3151 : {
3152 : // parse RHS (as tok has already been consumed in parse_expression)
3153 0 : auto right = parse_expr (LBP_PIPE, AST::AttrVec (), restrictions);
3154 0 : if (!right)
3155 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3156 :
3157 : // TODO: check types. actually, do so during semantic analysis
3158 0 : location_t locus = left->get_locus ();
3159 :
3160 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3161 0 : std::move (left), std::move (right.value ()),
3162 0 : ArithmeticOrLogicalOperator::BITWISE_OR, locus);
3163 0 : }
3164 :
3165 : /* Parses a binary bitwise (or eager logical) xor expression (with Pratt
3166 : * parsing). */
3167 : template <typename ManagedTokenSource>
3168 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3169 0 : Parser<ManagedTokenSource>::parse_bitwise_xor_expr (
3170 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3171 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3172 : {
3173 : // parse RHS (as tok has already been consumed in parse_expression)
3174 0 : auto right = parse_expr (LBP_CARET, AST::AttrVec (), restrictions);
3175 0 : if (!right)
3176 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3177 :
3178 : // TODO: check types. actually, do so during semantic analysis
3179 0 : location_t locus = left->get_locus ();
3180 :
3181 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3182 0 : std::move (left), std::move (right.value ()),
3183 0 : ArithmeticOrLogicalOperator::BITWISE_XOR, locus);
3184 0 : }
3185 :
3186 : // Parses a binary left shift expression (with Pratt parsing).
3187 : template <typename ManagedTokenSource>
3188 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3189 0 : Parser<ManagedTokenSource>::parse_left_shift_expr (
3190 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3191 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3192 : {
3193 : // parse RHS (as tok has already been consumed in parse_expression)
3194 0 : auto right = parse_expr (LBP_L_SHIFT, AST::AttrVec (), restrictions);
3195 0 : if (!right)
3196 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3197 :
3198 : // TODO: check types. actually, do so during semantic analysis
3199 0 : location_t locus = left->get_locus ();
3200 :
3201 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3202 0 : std::move (left), std::move (right.value ()),
3203 0 : ArithmeticOrLogicalOperator::LEFT_SHIFT, locus);
3204 0 : }
3205 :
3206 : // Parses a binary right shift expression (with Pratt parsing).
3207 : template <typename ManagedTokenSource>
3208 : tl::expected<std::unique_ptr<AST::ArithmeticOrLogicalExpr>, Parse::Error::Expr>
3209 0 : Parser<ManagedTokenSource>::parse_right_shift_expr (
3210 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3211 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3212 : {
3213 : // parse RHS (as tok has already been consumed in parse_expression)
3214 0 : auto right = parse_expr (LBP_R_SHIFT, AST::AttrVec (), restrictions);
3215 0 : if (!right)
3216 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3217 :
3218 : // TODO: check types. actually, do so during semantic analysis
3219 0 : location_t locus = left->get_locus ();
3220 :
3221 0 : return std::make_unique<AST::ArithmeticOrLogicalExpr> (
3222 0 : std::move (left), std::move (right.value ()),
3223 0 : ArithmeticOrLogicalOperator::RIGHT_SHIFT, locus);
3224 0 : }
3225 :
3226 : /* Returns the left binding power for the given ComparisonExpr type.
3227 : * TODO make constexpr? Would that even do anything useful? */
3228 : inline binding_powers
3229 5856 : get_lbp_for_comparison_expr (AST::ComparisonExpr::ExprType expr_type)
3230 : {
3231 5856 : switch (expr_type)
3232 : {
3233 : case ComparisonOperator::EQUAL:
3234 : return LBP_EQUAL;
3235 : case ComparisonOperator::NOT_EQUAL:
3236 : return LBP_NOT_EQUAL;
3237 : case ComparisonOperator::GREATER_THAN:
3238 : return LBP_GREATER_THAN;
3239 : case ComparisonOperator::LESS_THAN:
3240 : return LBP_SMALLER_THAN;
3241 : case ComparisonOperator::GREATER_OR_EQUAL:
3242 : return LBP_GREATER_EQUAL;
3243 : case ComparisonOperator::LESS_OR_EQUAL:
3244 : return LBP_SMALLER_EQUAL;
3245 0 : default:
3246 : // WTF? should not happen, this is an error
3247 0 : rust_unreachable ();
3248 :
3249 : return LBP_EQUAL;
3250 : }
3251 : }
3252 :
3253 : /* Parses a ComparisonExpr of given type and LBP. TODO find a way to only
3254 : * specify one and have the other looked up - e.g. specify ExprType and
3255 : * binding power is looked up? */
3256 : template <typename ManagedTokenSource>
3257 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3258 5856 : Parser<ManagedTokenSource>::parse_comparison_expr (
3259 : const_TokenPtr, std::unique_ptr<AST::Expr> left, AST::AttrVec,
3260 : AST::ComparisonExpr::ExprType expr_type, ParseRestrictions restrictions)
3261 : {
3262 : // parse RHS (as tok has already been consumed in parse_expression)
3263 5856 : auto right = parse_expr (get_lbp_for_comparison_expr (expr_type),
3264 11712 : AST::AttrVec (), restrictions);
3265 5856 : if (!right)
3266 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3267 :
3268 : // TODO: check types. actually, do so during semantic analysis
3269 5856 : location_t locus = left->get_locus ();
3270 :
3271 5856 : return std::make_unique<AST::ComparisonExpr> (std::move (left),
3272 5856 : std::move (right.value ()),
3273 5856 : expr_type, locus);
3274 5856 : }
3275 :
3276 : // Parses a binary equal to expression (with Pratt parsing).
3277 : template <typename ManagedTokenSource>
3278 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3279 0 : Parser<ManagedTokenSource>::parse_binary_equal_expr (
3280 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3281 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3282 : {
3283 : // parse RHS (as tok has already been consumed in parse_expression)
3284 0 : auto right = parse_expr (LBP_EQUAL, AST::AttrVec (), restrictions);
3285 0 : if (!right)
3286 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3287 :
3288 : // TODO: check types. actually, do so during semantic analysis
3289 0 : location_t locus = left->get_locus ();
3290 :
3291 0 : return std::make_unique<AST::ComparisonExpr> (std::move (left),
3292 0 : std::move (right.value ()),
3293 0 : ComparisonOperator::EQUAL,
3294 0 : locus);
3295 0 : }
3296 :
3297 : // Parses a binary not equal to expression (with Pratt parsing).
3298 : template <typename ManagedTokenSource>
3299 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3300 0 : Parser<ManagedTokenSource>::parse_binary_not_equal_expr (
3301 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3302 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3303 : {
3304 : // parse RHS (as tok has already been consumed in parse_expression)
3305 0 : auto right = parse_expr (LBP_NOT_EQUAL, AST::AttrVec (), restrictions);
3306 0 : if (!right)
3307 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3308 :
3309 : // TODO: check types. actually, do so during semantic analysis
3310 0 : location_t locus = left->get_locus ();
3311 :
3312 0 : return std::make_unique<AST::ComparisonExpr> (std::move (left),
3313 0 : std::move (right.value ()),
3314 0 : ComparisonOperator::NOT_EQUAL,
3315 0 : locus);
3316 0 : }
3317 :
3318 : // Parses a binary greater than expression (with Pratt parsing).
3319 : template <typename ManagedTokenSource>
3320 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3321 0 : Parser<ManagedTokenSource>::parse_binary_greater_than_expr (
3322 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3323 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3324 : {
3325 : // parse RHS (as tok has already been consumed in parse_expression)
3326 0 : auto right = parse_expr (LBP_GREATER_THAN, AST::AttrVec (), restrictions);
3327 0 : if (!right)
3328 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3329 :
3330 : // TODO: check types. actually, do so during semantic analysis
3331 0 : location_t locus = left->get_locus ();
3332 :
3333 0 : return std::make_unique<AST::ComparisonExpr> (
3334 0 : std::move (left), std::move (right.value ()),
3335 0 : ComparisonOperator::GREATER_THAN, locus);
3336 0 : }
3337 :
3338 : // Parses a binary less than expression (with Pratt parsing).
3339 : template <typename ManagedTokenSource>
3340 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3341 0 : Parser<ManagedTokenSource>::parse_binary_less_than_expr (
3342 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3343 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3344 : {
3345 : // parse RHS (as tok has already been consumed in parse_expression)
3346 0 : auto right = parse_expr (LBP_SMALLER_THAN, AST::AttrVec (), restrictions);
3347 0 : if (!right)
3348 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3349 :
3350 : // TODO: check types. actually, do so during semantic analysis
3351 0 : location_t locus = left->get_locus ();
3352 :
3353 0 : return std::make_unique<AST::ComparisonExpr> (std::move (left),
3354 0 : std::move (right.value ()),
3355 0 : ComparisonOperator::LESS_THAN,
3356 0 : locus);
3357 0 : }
3358 :
3359 : // Parses a binary greater than or equal to expression (with Pratt parsing).
3360 : template <typename ManagedTokenSource>
3361 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3362 0 : Parser<ManagedTokenSource>::parse_binary_greater_equal_expr (
3363 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3364 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3365 : {
3366 : // parse RHS (as tok has already been consumed in parse_expression)
3367 0 : auto right = parse_expr (LBP_GREATER_EQUAL, AST::AttrVec (), restrictions);
3368 0 : if (!right)
3369 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3370 :
3371 : // TODO: check types. actually, do so during semantic analysis
3372 0 : location_t locus = left->get_locus ();
3373 :
3374 0 : return std::make_unique<AST::ComparisonExpr> (
3375 0 : std::move (left), std::move (right.value ()),
3376 0 : ComparisonOperator::GREATER_OR_EQUAL, locus);
3377 0 : }
3378 :
3379 : // Parses a binary less than or equal to expression (with Pratt parsing).
3380 : template <typename ManagedTokenSource>
3381 : tl::expected<std::unique_ptr<AST::ComparisonExpr>, Parse::Error::Expr>
3382 0 : Parser<ManagedTokenSource>::parse_binary_less_equal_expr (
3383 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3384 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3385 : {
3386 : // parse RHS (as tok has already been consumed in parse_expression)
3387 0 : auto right = parse_expr (LBP_SMALLER_EQUAL, AST::AttrVec (), restrictions);
3388 0 : if (!right)
3389 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3390 :
3391 : // TODO: check types. actually, do so during semantic analysis
3392 0 : location_t locus = left->get_locus ();
3393 :
3394 0 : return std::make_unique<AST::ComparisonExpr> (
3395 0 : std::move (left), std::move (right.value ()),
3396 0 : ComparisonOperator::LESS_OR_EQUAL, locus);
3397 0 : }
3398 :
3399 : // Parses a binary lazy boolean or expression (with Pratt parsing).
3400 : template <typename ManagedTokenSource>
3401 : tl::expected<std::unique_ptr<AST::LazyBooleanExpr>, Parse::Error::Expr>
3402 264 : Parser<ManagedTokenSource>::parse_lazy_or_expr (
3403 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3404 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3405 : {
3406 : // parse RHS (as tok has already been consumed in parse_expression)
3407 264 : auto right = parse_expr (LBP_LOGICAL_OR, AST::AttrVec (), restrictions);
3408 264 : if (!right)
3409 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3410 :
3411 : // TODO: check types. actually, do so during semantic analysis
3412 264 : location_t locus = left->get_locus ();
3413 :
3414 264 : return std::make_unique<AST::LazyBooleanExpr> (
3415 264 : std::move (left), std::move (right.value ()),
3416 528 : LazyBooleanOperator::LOGICAL_OR, locus);
3417 264 : }
3418 :
3419 : // Parses a binary lazy boolean and expression (with Pratt parsing).
3420 : template <typename ManagedTokenSource>
3421 : tl::expected<std::unique_ptr<AST::LazyBooleanExpr>, Parse::Error::Expr>
3422 580 : Parser<ManagedTokenSource>::parse_lazy_and_expr (
3423 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3424 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3425 : {
3426 : // parse RHS (as tok has already been consumed in parse_expression)
3427 580 : auto right = parse_expr (LBP_LOGICAL_AND, AST::AttrVec (), restrictions);
3428 580 : if (!right)
3429 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3430 :
3431 : // TODO: check types. actually, do so during semantic analysis
3432 580 : location_t locus = left->get_locus ();
3433 :
3434 580 : return std::make_unique<AST::LazyBooleanExpr> (
3435 580 : std::move (left), std::move (right.value ()),
3436 1160 : LazyBooleanOperator::LOGICAL_AND, locus);
3437 580 : }
3438 :
3439 : // Parses a pseudo-binary infix type cast expression (with Pratt parsing).
3440 : template <typename ManagedTokenSource>
3441 : tl::expected<std::unique_ptr<AST::TypeCastExpr>, Parse::Error::Expr>
3442 9146 : Parser<ManagedTokenSource>::parse_type_cast_expr (
3443 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> expr_to_cast,
3444 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED,
3445 : ParseRestrictions restrictions ATTRIBUTE_UNUSED)
3446 : {
3447 : // parse RHS (as tok has already been consumed in parse_expression)
3448 9146 : auto type = parse_type_no_bounds ();
3449 9146 : if (!type)
3450 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3451 : // FIXME: how do I get precedence put in here?
3452 :
3453 : // TODO: check types. actually, do so during semantic analysis
3454 9146 : location_t locus = expr_to_cast->get_locus ();
3455 :
3456 9146 : return std::make_unique<AST::TypeCastExpr> (std::move (expr_to_cast),
3457 9146 : std::move (type), locus);
3458 9146 : }
3459 :
3460 : // Parses a binary assignment expression (with Pratt parsing).
3461 : template <typename ManagedTokenSource>
3462 : tl::expected<std::unique_ptr<AST::AssignmentExpr>, Parse::Error::Expr>
3463 3634 : Parser<ManagedTokenSource>::parse_assig_expr (
3464 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3465 : AST::AttrVec outer_attrs, ParseRestrictions restrictions)
3466 : {
3467 : // parse RHS (as tok has already been consumed in parse_expression)
3468 3634 : auto right = parse_expr (LBP_ASSIG - 1, AST::AttrVec (), restrictions);
3469 3634 : if (!right)
3470 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3471 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3472 :
3473 3634 : location_t locus = left->get_locus ();
3474 :
3475 3634 : return std::make_unique<AST::AssignmentExpr> (std::move (left),
3476 3634 : std::move (right.value ()),
3477 3634 : std::move (outer_attrs), locus);
3478 3634 : }
3479 :
3480 : /* Returns the left binding power for the given CompoundAssignmentExpr type.
3481 : * TODO make constexpr? Would that even do anything useful? */
3482 : inline binding_powers
3483 1544 : get_lbp_for_compound_assignment_expr (
3484 : AST::CompoundAssignmentExpr::ExprType expr_type)
3485 : {
3486 1544 : switch (expr_type)
3487 : {
3488 : case CompoundAssignmentOperator::ADD:
3489 : return LBP_PLUS;
3490 : case CompoundAssignmentOperator::SUBTRACT:
3491 : return LBP_MINUS;
3492 : case CompoundAssignmentOperator::MULTIPLY:
3493 : return LBP_MUL;
3494 : case CompoundAssignmentOperator::DIVIDE:
3495 : return LBP_DIV;
3496 : case CompoundAssignmentOperator::MODULUS:
3497 : return LBP_MOD;
3498 : case CompoundAssignmentOperator::BITWISE_AND:
3499 : return LBP_AMP;
3500 : case CompoundAssignmentOperator::BITWISE_OR:
3501 : return LBP_PIPE;
3502 : case CompoundAssignmentOperator::BITWISE_XOR:
3503 : return LBP_CARET;
3504 : case CompoundAssignmentOperator::LEFT_SHIFT:
3505 : return LBP_L_SHIFT;
3506 : case CompoundAssignmentOperator::RIGHT_SHIFT:
3507 : return LBP_R_SHIFT;
3508 0 : default:
3509 : // WTF? should not happen, this is an error
3510 0 : rust_unreachable ();
3511 :
3512 : return LBP_PLUS;
3513 : }
3514 : }
3515 :
3516 : // Parses a compound assignment expression (with Pratt parsing).
3517 : template <typename ManagedTokenSource>
3518 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3519 1544 : Parser<ManagedTokenSource>::parse_compound_assignment_expr (
3520 : const_TokenPtr, std::unique_ptr<AST::Expr> left, AST::AttrVec,
3521 : AST::CompoundAssignmentExpr::ExprType expr_type,
3522 : ParseRestrictions restrictions)
3523 : {
3524 : // parse RHS (as tok has already been consumed in parse_expression)
3525 1544 : auto right = parse_expr (get_lbp_for_compound_assignment_expr (expr_type) - 1,
3526 3088 : AST::AttrVec (), restrictions);
3527 1544 : if (!right)
3528 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3529 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3530 :
3531 : // TODO: check types. actually, do so during semantic analysis
3532 1544 : location_t locus = left->get_locus ();
3533 :
3534 1544 : return std::make_unique<AST::CompoundAssignmentExpr> (
3535 3088 : std::move (left), std::move (right.value ()), expr_type, locus);
3536 1544 : }
3537 :
3538 : // Parses a binary add-assignment expression (with Pratt parsing).
3539 : template <typename ManagedTokenSource>
3540 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3541 0 : Parser<ManagedTokenSource>::parse_plus_assig_expr (
3542 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3543 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3544 : {
3545 : // parse RHS (as tok has already been consumed in parse_expression)
3546 0 : auto right = parse_expr (LBP_PLUS_ASSIG - 1, AST::AttrVec (), restrictions);
3547 0 : if (!right)
3548 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3549 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3550 :
3551 : // TODO: check types. actually, do so during semantic analysis
3552 0 : location_t locus = left->get_locus ();
3553 :
3554 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3555 0 : std::move (left), std::move (right.value ()),
3556 0 : CompoundAssignmentOperator::ADD, locus);
3557 0 : }
3558 :
3559 : // Parses a binary minus-assignment expression (with Pratt parsing).
3560 : template <typename ManagedTokenSource>
3561 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3562 0 : Parser<ManagedTokenSource>::parse_minus_assig_expr (
3563 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3564 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3565 : {
3566 : // parse RHS (as tok has already been consumed in parse_expression)
3567 0 : auto right = parse_expr (LBP_MINUS_ASSIG - 1, AST::AttrVec (), restrictions);
3568 0 : if (!right)
3569 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3570 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3571 :
3572 : // TODO: check types. actually, do so during semantic analysis
3573 0 : location_t locus = left->get_locus ();
3574 :
3575 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3576 0 : std::move (left), std::move (right.value ()),
3577 0 : CompoundAssignmentOperator::SUBTRACT, locus);
3578 0 : }
3579 :
3580 : // Parses a binary multiplication-assignment expression (with Pratt parsing).
3581 : template <typename ManagedTokenSource>
3582 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3583 0 : Parser<ManagedTokenSource>::parse_mult_assig_expr (
3584 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3585 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3586 : {
3587 : // parse RHS (as tok has already been consumed in parse_expression)
3588 0 : auto right = parse_expr (LBP_MULT_ASSIG - 1, AST::AttrVec (), restrictions);
3589 0 : if (!right)
3590 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3591 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3592 :
3593 : // TODO: check types. actually, do so during semantic analysis
3594 0 : location_t locus = left->get_locus ();
3595 :
3596 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3597 0 : std::move (left), std::move (right.value ()),
3598 0 : CompoundAssignmentOperator::MULTIPLY, locus);
3599 0 : }
3600 :
3601 : // Parses a binary division-assignment expression (with Pratt parsing).
3602 : template <typename ManagedTokenSource>
3603 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3604 0 : Parser<ManagedTokenSource>::parse_div_assig_expr (
3605 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3606 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3607 : {
3608 : // parse RHS (as tok has already been consumed in parse_expression)
3609 0 : auto right = parse_expr (LBP_DIV_ASSIG - 1, AST::AttrVec (), restrictions);
3610 0 : if (!right)
3611 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3612 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3613 :
3614 : // TODO: check types. actually, do so during semantic analysis
3615 0 : location_t locus = left->get_locus ();
3616 :
3617 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3618 0 : std::move (left), std::move (right.value ()),
3619 0 : CompoundAssignmentOperator::DIVIDE, locus);
3620 0 : }
3621 :
3622 : // Parses a binary modulo-assignment expression (with Pratt parsing).
3623 : template <typename ManagedTokenSource>
3624 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3625 0 : Parser<ManagedTokenSource>::parse_mod_assig_expr (
3626 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3627 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3628 : {
3629 : // parse RHS (as tok has already been consumed in parse_expression)
3630 0 : auto right = parse_expr (LBP_MOD_ASSIG - 1, AST::AttrVec (), restrictions);
3631 0 : if (!right)
3632 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3633 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3634 :
3635 : // TODO: check types. actually, do so during semantic analysis
3636 0 : location_t locus = left->get_locus ();
3637 :
3638 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3639 0 : std::move (left), std::move (right.value ()),
3640 0 : CompoundAssignmentOperator::MODULUS, locus);
3641 0 : }
3642 :
3643 : // Parses a binary and-assignment expression (with Pratt parsing).
3644 : template <typename ManagedTokenSource>
3645 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3646 0 : Parser<ManagedTokenSource>::parse_and_assig_expr (
3647 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3648 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3649 : {
3650 : // parse RHS (as tok has already been consumed in parse_expression)
3651 0 : auto right = parse_expr (LBP_AMP_ASSIG - 1, AST::AttrVec (), restrictions);
3652 0 : if (!right)
3653 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3654 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3655 :
3656 : // TODO: check types. actually, do so during semantic analysis
3657 0 : location_t locus = left->get_locus ();
3658 :
3659 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3660 0 : std::move (left), std::move (right.value ()),
3661 0 : CompoundAssignmentOperator::BITWISE_AND, locus);
3662 0 : }
3663 :
3664 : // Parses a binary or-assignment expression (with Pratt parsing).
3665 : template <typename ManagedTokenSource>
3666 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3667 0 : Parser<ManagedTokenSource>::parse_or_assig_expr (
3668 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3669 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3670 : {
3671 : // parse RHS (as tok has already been consumed in parse_expression)
3672 0 : auto right = parse_expr (LBP_PIPE_ASSIG - 1, AST::AttrVec (), restrictions);
3673 0 : if (!right)
3674 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3675 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3676 :
3677 : // TODO: check types. actually, do so during semantic analysis
3678 0 : location_t locus = left->get_locus ();
3679 :
3680 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3681 0 : std::move (left), std::move (right.value ()),
3682 0 : CompoundAssignmentOperator::BITWISE_OR, locus);
3683 0 : }
3684 :
3685 : // Parses a binary xor-assignment expression (with Pratt parsing).
3686 : template <typename ManagedTokenSource>
3687 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3688 0 : Parser<ManagedTokenSource>::parse_xor_assig_expr (
3689 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3690 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3691 : {
3692 : // parse RHS (as tok has already been consumed in parse_expression)
3693 0 : auto right = parse_expr (LBP_CARET_ASSIG - 1, AST::AttrVec (), restrictions);
3694 0 : if (!right)
3695 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3696 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3697 :
3698 : // TODO: check types. actually, do so during semantic analysis
3699 0 : location_t locus = left->get_locus ();
3700 :
3701 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3702 0 : std::move (left), std::move (right.value ()),
3703 0 : CompoundAssignmentOperator::BITWISE_XOR, locus);
3704 0 : }
3705 :
3706 : // Parses a binary left shift-assignment expression (with Pratt parsing).
3707 : template <typename ManagedTokenSource>
3708 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3709 0 : Parser<ManagedTokenSource>::parse_left_shift_assig_expr (
3710 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3711 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3712 : {
3713 : // parse RHS (as tok has already been consumed in parse_expression)
3714 0 : auto right
3715 0 : = parse_expr (LBP_L_SHIFT_ASSIG - 1, AST::AttrVec (), restrictions);
3716 0 : if (!right)
3717 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3718 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3719 :
3720 : // TODO: check types. actually, do so during semantic analysis
3721 0 : location_t locus = left->get_locus ();
3722 :
3723 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3724 0 : std::move (left), std::move (right.value ()),
3725 0 : CompoundAssignmentOperator::LEFT_SHIFT, locus);
3726 0 : }
3727 :
3728 : // Parses a binary right shift-assignment expression (with Pratt parsing).
3729 : template <typename ManagedTokenSource>
3730 : tl::expected<std::unique_ptr<AST::CompoundAssignmentExpr>, Parse::Error::Expr>
3731 0 : Parser<ManagedTokenSource>::parse_right_shift_assig_expr (
3732 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3733 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3734 : {
3735 : // parse RHS (as tok has already been consumed in parse_expression)
3736 0 : auto right
3737 0 : = parse_expr (LBP_R_SHIFT_ASSIG - 1, AST::AttrVec (), restrictions);
3738 0 : if (!right)
3739 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3740 : // FIXME: ensure right-associativity for this - 'LBP - 1' may do this?
3741 :
3742 : // TODO: check types. actually, do so during semantic analysis
3743 0 : location_t locus = left->get_locus ();
3744 :
3745 0 : return std::make_unique<AST::CompoundAssignmentExpr> (
3746 0 : std::move (left), std::move (right.value ()),
3747 0 : CompoundAssignmentOperator::RIGHT_SHIFT, locus);
3748 0 : }
3749 :
3750 : // Parses a postfix unary await expression (with Pratt parsing).
3751 : template <typename ManagedTokenSource>
3752 : tl::expected<std::unique_ptr<AST::AwaitExpr>, Parse::Error::Expr>
3753 0 : Parser<ManagedTokenSource>::parse_await_expr (
3754 : const_TokenPtr tok, std::unique_ptr<AST::Expr> expr_to_await,
3755 : AST::AttrVec outer_attrs)
3756 : {
3757 : /* skip "await" identifier (as "." has already been consumed in
3758 : * parse_expression) this assumes that the identifier was already identified
3759 : * as await */
3760 0 : if (!skip_token (IDENTIFIER))
3761 : {
3762 0 : Error error (tok->get_locus (), "failed to skip %<await%> in await expr "
3763 : "- this is probably a deep issue");
3764 0 : add_error (std::move (error));
3765 :
3766 : // skip somewhere?
3767 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
3768 0 : }
3769 :
3770 : // TODO: check inside async block in semantic analysis
3771 0 : location_t locus = expr_to_await->get_locus ();
3772 :
3773 0 : return std::unique_ptr<AST::AwaitExpr> (
3774 0 : new AST::AwaitExpr (std::move (expr_to_await), std::move (outer_attrs),
3775 0 : locus));
3776 : }
3777 :
3778 : /* Parses an exclusive range ('..') in left denotation position (i.e.
3779 : * RangeFromExpr or RangeFromToExpr). */
3780 : template <typename ManagedTokenSource>
3781 : tl::expected<std::unique_ptr<AST::RangeExpr>, Parse::Error::Expr>
3782 362 : Parser<ManagedTokenSource>::parse_led_range_exclusive_expr (
3783 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3784 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3785 : {
3786 : // FIXME: this probably parses expressions accidently or whatever
3787 : // try parsing RHS (as tok has already been consumed in parse_expression)
3788 : // Can be nullptr, in which case it is a RangeFromExpr, otherwise a
3789 : // RangeFromToExpr.
3790 362 : restrictions.expr_can_be_null = true;
3791 362 : auto right = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions);
3792 :
3793 362 : location_t locus = left->get_locus ();
3794 :
3795 362 : if (!right)
3796 : {
3797 : // range from expr
3798 71 : return std::make_unique<AST::RangeFromExpr> (std::move (left), locus);
3799 : }
3800 : else
3801 : {
3802 291 : return std::make_unique<AST::RangeFromToExpr> (std::move (left),
3803 291 : std::move (right.value ()),
3804 291 : locus);
3805 : }
3806 : // FIXME: make non-associative
3807 362 : }
3808 :
3809 : /* Parses an exclusive range ('..') in null denotation position (i.e.
3810 : * RangeToExpr or RangeFullExpr). */
3811 : template <typename ManagedTokenSource>
3812 : tl::expected<std::unique_ptr<AST::RangeExpr>, Parse::Error::Expr>
3813 173 : Parser<ManagedTokenSource>::parse_nud_range_exclusive_expr (
3814 : const_TokenPtr tok, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED)
3815 : {
3816 173 : auto restrictions = ParseRestrictions ();
3817 173 : restrictions.expr_can_be_null = true;
3818 :
3819 : // FIXME: this probably parses expressions accidently or whatever
3820 : // try parsing RHS (as tok has already been consumed in parse_expression)
3821 173 : auto right = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions);
3822 :
3823 173 : location_t locus = tok->get_locus ();
3824 :
3825 173 : if (!right)
3826 : {
3827 : // range from expr
3828 54 : return std::make_unique<AST::RangeFullExpr> (locus);
3829 : }
3830 : else
3831 : {
3832 119 : return std::make_unique<AST::RangeToExpr> (std::move (right.value ()),
3833 119 : locus);
3834 : }
3835 : // FIXME: make non-associative
3836 173 : }
3837 :
3838 : // Parses a full binary range inclusive expression.
3839 : template <typename ManagedTokenSource>
3840 : tl::expected<std::unique_ptr<AST::RangeFromToInclExpr>, Parse::Error::Expr>
3841 13 : Parser<ManagedTokenSource>::parse_range_inclusive_expr (
3842 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> left,
3843 : AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions)
3844 : {
3845 : // parse RHS (as tok has already been consumed in parse_expression)
3846 13 : auto right = parse_expr (LBP_DOT_DOT_EQ, AST::AttrVec (), restrictions);
3847 13 : if (!right)
3848 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3849 : // FIXME: make non-associative
3850 :
3851 : // TODO: check types. actually, do so during semantic analysis
3852 13 : location_t locus = left->get_locus ();
3853 :
3854 13 : return std::make_unique<AST::RangeFromToInclExpr> (std::move (left),
3855 13 : std::move (right.value ()),
3856 13 : locus);
3857 13 : }
3858 :
3859 : // Parses an inclusive range-to prefix unary expression.
3860 : template <typename ManagedTokenSource>
3861 : tl::expected<std::unique_ptr<AST::RangeToInclExpr>, Parse::Error::Expr>
3862 0 : Parser<ManagedTokenSource>::parse_range_to_inclusive_expr (
3863 : const_TokenPtr tok, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED)
3864 : {
3865 : // parse RHS (as tok has already been consumed in parse_expression)
3866 0 : auto right = parse_expr (LBP_DOT_DOT_EQ);
3867 0 : if (!right)
3868 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3869 : // FIXME: make non-associative
3870 :
3871 : // TODO: check types. actually, do so during semantic analysis
3872 :
3873 0 : return std::make_unique<AST::RangeToInclExpr> (std::move (right.value ()),
3874 0 : tok->get_locus ());
3875 0 : }
3876 :
3877 : // Parses a pseudo-binary infix tuple index expression.
3878 : template <typename ManagedTokenSource>
3879 : tl::expected<std::unique_ptr<AST::TupleIndexExpr>, Parse::Error::Expr>
3880 8950 : Parser<ManagedTokenSource>::parse_tuple_index_expr (
3881 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> tuple_expr,
3882 : AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED)
3883 : {
3884 : // parse int literal (as token already skipped)
3885 8950 : const_TokenPtr index_tok = expect_token (INT_LITERAL);
3886 8950 : if (index_tok == nullptr)
3887 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
3888 :
3889 17900 : std::string index = index_tok->get_str ();
3890 :
3891 : // convert to integer
3892 8950 : if (!index_tok->is_pure_decimal ())
3893 : {
3894 27 : Error error (index_tok->get_locus (),
3895 : "tuple index should be a pure decimal literal");
3896 27 : add_error (std::move (error));
3897 27 : }
3898 8950 : int index_int = atoi (index.c_str ());
3899 :
3900 8950 : location_t locus = tuple_expr->get_locus ();
3901 :
3902 8950 : return std::make_unique<AST::TupleIndexExpr> (std::move (tuple_expr),
3903 : index_int,
3904 8950 : std::move (outer_attrs), locus);
3905 8950 : }
3906 :
3907 : // Parses a pseudo-binary infix array (or slice) index expression.
3908 : template <typename ManagedTokenSource>
3909 : tl::expected<std::unique_ptr<AST::ArrayIndexExpr>, Parse::Error::Expr>
3910 865 : Parser<ManagedTokenSource>::parse_index_expr (
3911 : const_TokenPtr, std::unique_ptr<AST::Expr> array_expr,
3912 : AST::AttrVec outer_attrs, ParseRestrictions)
3913 : {
3914 : // parse RHS (as tok has already been consumed in parse_expression)
3915 : /*std::unique_ptr<AST::Expr> index_expr
3916 : = parse_expr (LBP_ARRAY_REF, AST::AttrVec (),
3917 : restrictions);*/
3918 : // TODO: conceptually, should treat [] as brackets, so just parse all expr
3919 865 : auto index_expr = parse_expr ();
3920 865 : if (!index_expr)
3921 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::CHILD_ERROR);
3922 :
3923 : // skip ']' at end of array
3924 865 : if (!skip_token (RIGHT_SQUARE))
3925 : {
3926 : // skip somewhere?
3927 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
3928 : }
3929 :
3930 : // TODO: check types. actually, do so during semantic analysis
3931 865 : location_t locus = array_expr->get_locus ();
3932 :
3933 865 : return std::make_unique<AST::ArrayIndexExpr> (std::move (array_expr),
3934 865 : std::move (index_expr.value ()),
3935 865 : std::move (outer_attrs), locus);
3936 865 : }
3937 :
3938 : // Parses a pseudo-binary infix struct field access expression.
3939 : template <typename ManagedTokenSource>
3940 : tl::expected<std::unique_ptr<AST::FieldAccessExpr>, Parse::Error::Expr>
3941 7877 : Parser<ManagedTokenSource>::parse_field_access_expr (
3942 : const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> struct_expr,
3943 : AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED)
3944 : {
3945 : /* get field name identifier (assume that this is a field access expr and
3946 : * not await, for instance) */
3947 7877 : const_TokenPtr ident_tok = expect_token (IDENTIFIER);
3948 7877 : if (ident_tok == nullptr)
3949 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
3950 :
3951 15754 : Identifier ident{ident_tok};
3952 :
3953 7877 : location_t locus = struct_expr->get_locus ();
3954 :
3955 : // TODO: check types. actually, do so during semantic analysis
3956 7877 : return std::make_unique<AST::FieldAccessExpr> (std::move (struct_expr),
3957 : std::move (ident),
3958 : std::move (outer_attrs),
3959 7877 : locus);
3960 7877 : }
3961 :
3962 : // Parses a pseudo-binary infix method call expression.
3963 : template <typename ManagedTokenSource>
3964 : tl::expected<std::unique_ptr<AST::MethodCallExpr>, Parse::Error::Expr>
3965 29755 : Parser<ManagedTokenSource>::parse_method_call_expr (
3966 : const_TokenPtr tok, std::unique_ptr<AST::Expr> receiver_expr,
3967 : AST::AttrVec outer_attrs, ParseRestrictions)
3968 : {
3969 : // parse path expr segment
3970 29755 : AST::PathExprSegment segment = parse_path_expr_segment ();
3971 29755 : if (segment.is_error ())
3972 : {
3973 0 : Error error (tok->get_locus (),
3974 : "failed to parse path expr segment of method call expr");
3975 0 : add_error (std::move (error));
3976 :
3977 : return tl::unexpected<Parse::Error::Expr> (
3978 0 : Parse::Error::Expr::CHILD_ERROR);
3979 0 : }
3980 :
3981 : // skip left parentheses
3982 29755 : if (!skip_token (LEFT_PAREN))
3983 : {
3984 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
3985 : }
3986 :
3987 : // parse method params (if they exist)
3988 29755 : std::vector<std::unique_ptr<AST::Expr>> params;
3989 :
3990 29755 : const_TokenPtr t = lexer.peek_token ();
3991 35928 : while (t->get_id () != RIGHT_PAREN)
3992 : {
3993 6173 : auto param = parse_expr ();
3994 6173 : if (!param)
3995 : {
3996 0 : Error error (t->get_locus (),
3997 : "failed to parse method param in method call");
3998 0 : add_error (std::move (error));
3999 :
4000 : return tl::unexpected<Parse::Error::Expr> (
4001 0 : Parse::Error::Expr::CHILD_ERROR);
4002 0 : }
4003 6173 : params.push_back (std::move (param.value ()));
4004 :
4005 12346 : if (lexer.peek_token ()->get_id () != COMMA)
4006 : break;
4007 :
4008 419 : lexer.skip_token ();
4009 419 : t = lexer.peek_token ();
4010 : }
4011 :
4012 : // skip right paren
4013 29755 : if (!skip_token (RIGHT_PAREN))
4014 : {
4015 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4016 : }
4017 :
4018 : // TODO: check types. actually do so in semantic analysis pass.
4019 29755 : location_t locus = receiver_expr->get_locus ();
4020 :
4021 29755 : return std::make_unique<AST::MethodCallExpr> (std::move (receiver_expr),
4022 : std::move (segment),
4023 : std::move (params),
4024 29755 : std::move (outer_attrs), locus);
4025 29755 : }
4026 :
4027 : // Parses a pseudo-binary infix function call expression.
4028 : template <typename ManagedTokenSource>
4029 : tl::expected<std::unique_ptr<AST::CallExpr>, Parse::Error::Expr>
4030 1269 : Parser<ManagedTokenSource>::parse_function_call_expr (
4031 : const_TokenPtr, std::unique_ptr<AST::Expr> function_expr,
4032 : AST::AttrVec outer_attrs, ParseRestrictions)
4033 : {
4034 : // parse function params (if they exist)
4035 1269 : std::vector<std::unique_ptr<AST::Expr>> params;
4036 :
4037 1269 : const_TokenPtr t = lexer.peek_token ();
4038 2478 : while (t->get_id () != RIGHT_PAREN)
4039 : {
4040 1209 : auto param = parse_expr ();
4041 1209 : if (!param)
4042 : {
4043 0 : Error error (t->get_locus (),
4044 : "failed to parse function param in function call");
4045 0 : add_error (std::move (error));
4046 :
4047 : return tl::unexpected<Parse::Error::Expr> (
4048 0 : Parse::Error::Expr::CHILD_ERROR);
4049 0 : }
4050 1209 : params.push_back (std::move (param.value ()));
4051 :
4052 2418 : if (lexer.peek_token ()->get_id () != COMMA)
4053 : break;
4054 :
4055 107 : lexer.skip_token ();
4056 107 : t = lexer.peek_token ();
4057 : }
4058 :
4059 : // skip ')' at end of param list
4060 1269 : if (!skip_token (RIGHT_PAREN))
4061 : {
4062 : // skip somewhere?
4063 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4064 : }
4065 :
4066 : // TODO: check types. actually, do so during semantic analysis
4067 1269 : location_t locus = function_expr->get_locus ();
4068 :
4069 1269 : return std::make_unique<AST::CallExpr> (std::move (function_expr),
4070 : std::move (params),
4071 1269 : std::move (outer_attrs), locus);
4072 1269 : }
4073 :
4074 : /* Parses a struct expr struct with a path in expression already parsed (but
4075 : * not
4076 : * '{' token). */
4077 : template <typename ManagedTokenSource>
4078 : tl::expected<std::unique_ptr<AST::StructExprStruct>, Parse::Error::Expr>
4079 1757 : Parser<ManagedTokenSource>::parse_struct_expr_struct_partial (
4080 : AST::PathInExpression path, AST::AttrVec outer_attrs)
4081 : {
4082 : // assume struct expr struct (as struct-enum disambiguation requires name
4083 : // lookup) again, make statement if final ';'
4084 1757 : if (!skip_token (LEFT_CURLY))
4085 : {
4086 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4087 : }
4088 :
4089 : // parse inner attributes
4090 1757 : AST::AttrVec inner_attrs = parse_inner_attributes ();
4091 :
4092 : // branch based on next token
4093 1757 : const_TokenPtr t = lexer.peek_token ();
4094 1757 : location_t path_locus = path.get_locus ();
4095 1757 : switch (t->get_id ())
4096 : {
4097 78 : case RIGHT_CURLY:
4098 : // struct with no body
4099 78 : lexer.skip_token ();
4100 :
4101 78 : return std::make_unique<AST::StructExprStruct> (std::move (path),
4102 : std::move (inner_attrs),
4103 : std::move (outer_attrs),
4104 78 : path_locus);
4105 1679 : case DOT_DOT:
4106 : /* technically this would give a struct base-only struct, but this
4107 : * algorithm should work too. As such, AST type not happening. */
4108 : case IDENTIFIER:
4109 : case HASH:
4110 : case INT_LITERAL:
4111 : {
4112 : // struct with struct expr fields
4113 :
4114 : // parse struct expr fields
4115 1679 : std::vector<std::unique_ptr<AST::StructExprField>> fields;
4116 :
4117 4622 : while (t->get_id () != RIGHT_CURLY && t->get_id () != DOT_DOT)
4118 : {
4119 2943 : auto field = parse_struct_expr_field ();
4120 2943 : if (!field)
4121 : {
4122 1 : if (field.error () == Parse::Error::StructExprField::STRUCT_BASE)
4123 : break;
4124 1 : if (field.error ()
4125 : == Parse::Error::StructExprField::STRUCT_BASE_ATTRIBUTES)
4126 : return tl::unexpected<Parse::Error::Expr> (
4127 1 : Parse::Error::Expr::CHILD_ERROR);
4128 :
4129 0 : Error error (t->get_locus (),
4130 : "failed to parse struct (or enum) expr field");
4131 0 : add_error (std::move (error));
4132 :
4133 : return tl::unexpected<Parse::Error::Expr> (
4134 0 : Parse::Error::Expr::CHILD_ERROR);
4135 0 : }
4136 :
4137 : // DEBUG:
4138 2942 : rust_debug ("struct/enum expr field validated to not be null");
4139 :
4140 2942 : fields.push_back (std::move (field.value ()));
4141 :
4142 : // DEBUG:
4143 2942 : rust_debug ("struct/enum expr field pushed back");
4144 :
4145 5884 : if (lexer.peek_token ()->get_id () != COMMA)
4146 : {
4147 : // DEBUG:
4148 1369 : rust_debug ("lack of comma detected in struct/enum expr "
4149 : "fields - break");
4150 1369 : break;
4151 : }
4152 1573 : lexer.skip_token ();
4153 :
4154 : // DEBUG:
4155 1573 : rust_debug ("struct/enum expr fields comma skipped ");
4156 :
4157 1573 : t = lexer.peek_token ();
4158 : }
4159 :
4160 : // DEBUG:
4161 1678 : rust_debug ("struct/enum expr about to parse struct base ");
4162 :
4163 : // parse struct base if it exists
4164 : AST::StructBase struct_base = AST::StructBase::error ();
4165 3356 : if (lexer.peek_token ()->get_id () == DOT_DOT)
4166 : {
4167 69 : location_t dot_dot_location = lexer.peek_token ()->get_locus ();
4168 69 : lexer.skip_token ();
4169 :
4170 : // parse required struct base expr
4171 69 : auto base_expr = parse_expr ();
4172 69 : if (!base_expr)
4173 : {
4174 0 : Error error (lexer.peek_token ()->get_locus (),
4175 : "failed to parse struct base expression in struct "
4176 : "expression");
4177 0 : add_error (std::move (error));
4178 :
4179 : return tl::unexpected<Parse::Error::Expr> (
4180 0 : Parse::Error::Expr::CHILD_ERROR);
4181 0 : }
4182 :
4183 : // DEBUG:
4184 69 : rust_debug ("struct/enum expr - parsed and validated base expr");
4185 :
4186 138 : struct_base = AST::StructBase (std::move (base_expr.value ()),
4187 69 : dot_dot_location);
4188 :
4189 : // DEBUG:
4190 69 : rust_debug ("assigned struct base to new struct base ");
4191 69 : }
4192 :
4193 1678 : if (!skip_token (RIGHT_CURLY))
4194 : {
4195 : return tl::unexpected<Parse::Error::Expr> (
4196 0 : Parse::Error::Expr::MALFORMED);
4197 : }
4198 :
4199 : // DEBUG:
4200 1678 : rust_debug (
4201 : "struct/enum expr skipped right curly - done and ready to return");
4202 :
4203 1678 : return std::make_unique<AST::StructExprStructFields> (
4204 : std::move (path), std::move (fields), path_locus,
4205 : std::move (struct_base), std::move (inner_attrs),
4206 1678 : std::move (outer_attrs));
4207 1679 : }
4208 0 : default:
4209 0 : add_error (
4210 0 : Error (t->get_locus (),
4211 : "unrecognised token %qs in struct (or enum) expression - "
4212 : "expected %<}%>, identifier, integer literal, or %<..%>",
4213 : t->get_token_description ()));
4214 :
4215 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4216 : }
4217 1757 : }
4218 :
4219 : /* Parses a struct expr tuple with a path in expression already parsed (but
4220 : * not
4221 : * '(' token).
4222 : * FIXME: this currently outputs a call expr, as they cannot be disambiguated.
4223 : * A better solution would be to just get this to call that function directly.
4224 : * */
4225 : template <typename ManagedTokenSource>
4226 : tl::expected<std::unique_ptr<AST::CallExpr>, Parse::Error::Expr>
4227 79737 : Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial (
4228 : AST::PathInExpression path, AST::AttrVec outer_attrs)
4229 : {
4230 79737 : if (!skip_token (LEFT_PAREN))
4231 : {
4232 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4233 : }
4234 :
4235 79737 : AST::AttrVec inner_attrs = parse_inner_attributes ();
4236 :
4237 79737 : std::vector<std::unique_ptr<AST::Expr>> exprs;
4238 :
4239 79737 : const_TokenPtr t = lexer.peek_token ();
4240 290114 : while (t->get_id () != RIGHT_PAREN)
4241 : {
4242 : // parse expression (required)
4243 210377 : auto expr = parse_expr ();
4244 210377 : if (!expr)
4245 : {
4246 0 : Error error (t->get_locus (), "failed to parse expression in "
4247 : "struct (or enum) expression tuple");
4248 0 : add_error (std::move (error));
4249 :
4250 : return tl::unexpected<Parse::Error::Expr> (
4251 0 : Parse::Error::Expr::CHILD_ERROR);
4252 0 : }
4253 210377 : exprs.push_back (std::move (expr.value ()));
4254 :
4255 420754 : if (lexer.peek_token ()->get_id () != COMMA)
4256 : break;
4257 :
4258 142385 : lexer.skip_token ();
4259 :
4260 142385 : t = lexer.peek_token ();
4261 : }
4262 :
4263 79737 : if (!skip_token (RIGHT_PAREN))
4264 : {
4265 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4266 : }
4267 :
4268 79737 : location_t path_locus = path.get_locus ();
4269 :
4270 79737 : auto pathExpr = std::make_unique<AST::PathInExpression> (std::move (path));
4271 :
4272 79737 : return std::make_unique<AST::CallExpr> (std::move (pathExpr),
4273 : std::move (exprs),
4274 79737 : std::move (outer_attrs), path_locus);
4275 159474 : }
4276 :
4277 : // Parses a closure expression with pratt parsing (from null denotation).
4278 : template <typename ManagedTokenSource>
4279 : tl::expected<std::unique_ptr<AST::ClosureExpr>, Parse::Error::Expr>
4280 382 : Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok,
4281 : AST::AttrVec outer_attrs)
4282 : {
4283 : // TODO: does this need pratt parsing (for precedence)? probably not, but
4284 : // idk
4285 382 : location_t locus = tok->get_locus ();
4286 382 : bool has_move = false;
4287 382 : if (tok->get_id () == MOVE)
4288 : {
4289 60 : has_move = true;
4290 60 : tok = lexer.peek_token ();
4291 60 : lexer.skip_token ();
4292 : // skip token and reassign
4293 : }
4294 :
4295 : // handle parameter list
4296 382 : std::vector<AST::ClosureParam> params;
4297 :
4298 382 : switch (tok->get_id ())
4299 : {
4300 : case OR:
4301 : // no parameters, don't skip token
4302 : break;
4303 357 : case PIPE:
4304 : {
4305 : // actually may have parameters
4306 : // don't skip token
4307 357 : const_TokenPtr t = lexer.peek_token ();
4308 797 : while (t->get_id () != PIPE)
4309 : {
4310 440 : AST::ClosureParam param = parse_closure_param ();
4311 440 : if (param.is_error ())
4312 : {
4313 : // TODO is this really an error?
4314 0 : Error error (t->get_locus (), "could not parse closure param");
4315 0 : add_error (std::move (error));
4316 :
4317 : return tl::unexpected<Parse::Error::Expr> (
4318 0 : Parse::Error::Expr::CHILD_ERROR);
4319 0 : }
4320 440 : params.push_back (std::move (param));
4321 :
4322 880 : if (lexer.peek_token ()->get_id () != COMMA)
4323 : {
4324 714 : if (lexer.peek_token ()->get_id () == OR)
4325 1 : lexer.split_current_token (PIPE, PIPE);
4326 : // not an error but means param list is done
4327 : break;
4328 : }
4329 : // skip comma
4330 83 : lexer.skip_token ();
4331 :
4332 166 : if (lexer.peek_token ()->get_id () == OR)
4333 0 : lexer.split_current_token (PIPE, PIPE);
4334 :
4335 83 : t = lexer.peek_token ();
4336 : }
4337 :
4338 357 : if (!skip_token (PIPE))
4339 : {
4340 : return tl::unexpected<Parse::Error::Expr> (
4341 0 : Parse::Error::Expr::MALFORMED);
4342 : }
4343 : break;
4344 357 : }
4345 0 : default:
4346 0 : add_error (Error (tok->get_locus (),
4347 : "unexpected token %qs in closure expression - expected "
4348 : "%<|%> or %<||%>",
4349 : tok->get_token_description ()));
4350 :
4351 : // skip somewhere?
4352 0 : return tl::unexpected<Parse::Error::Expr> (Parse::Error::Expr::MALFORMED);
4353 : }
4354 :
4355 : // again branch based on next token
4356 382 : tok = lexer.peek_token ();
4357 382 : if (tok->get_id () == RETURN_TYPE)
4358 : {
4359 : // must be return type closure with block expr
4360 :
4361 : // skip "return type" token
4362 32 : lexer.skip_token ();
4363 :
4364 : // parse actual type, which is required
4365 32 : auto type = parse_type_no_bounds ();
4366 32 : if (!type)
4367 : {
4368 : // error
4369 0 : Error error (tok->get_locus (), "failed to parse type for closure");
4370 0 : add_error (std::move (error));
4371 :
4372 : // skip somewhere?
4373 : return tl::unexpected<Parse::Error::Expr> (
4374 0 : Parse::Error::Expr::CHILD_ERROR);
4375 0 : }
4376 :
4377 : // parse block expr, which is required
4378 32 : auto block = parse_block_expr ();
4379 32 : if (!block)
4380 : {
4381 : // error
4382 0 : Error error (lexer.peek_token ()->get_locus (),
4383 : "failed to parse block expr in closure");
4384 0 : add_error (std::move (error));
4385 :
4386 : // skip somewhere?
4387 : return tl::unexpected<Parse::Error::Expr> (
4388 0 : Parse::Error::Expr::CHILD_ERROR);
4389 0 : }
4390 :
4391 32 : return std::make_unique<AST::ClosureExprInnerTyped> (
4392 32 : std::move (type), std::move (block.value ()), std::move (params), locus,
4393 32 : has_move, std::move (outer_attrs));
4394 32 : }
4395 : else
4396 : {
4397 : // must be expr-only closure
4398 :
4399 : // parse expr, which is required
4400 350 : auto expr = parse_expr ();
4401 350 : if (!expr)
4402 : {
4403 0 : Error error (tok->get_locus (),
4404 : "failed to parse expression in closure");
4405 0 : add_error (std::move (error));
4406 :
4407 : // skip somewhere?
4408 : return tl::unexpected<Parse::Error::Expr> (
4409 0 : Parse::Error::Expr::CHILD_ERROR);
4410 0 : }
4411 :
4412 350 : return std::make_unique<AST::ClosureExprInner> (std::move (expr.value ()),
4413 : std::move (params), locus,
4414 : has_move,
4415 350 : std::move (outer_attrs));
4416 350 : }
4417 382 : }
4418 :
4419 : } // namespace Rust
|