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