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