GCC Code Coverage Report


Directory: ./
File: src/parser/parser.cpp
Date: 2023-04-27 00:55:30
Exec Total Coverage
Lines: 1112 1225 90.8%
Functions: 287 320 89.7%
Branches: 1361 1737 78.4%

Line Branch Exec Source
1 #include "parser.h"
2 #include "ast/magic.h"
3 #include "ast/ops.h"
4 #include "utilities/guard.h"
5 #include "utilities/strings.h"
6
7 #define TRACE_START2(tok) \
8 kwtrace_start( \
9 depth, "{}: {} - `{}`", to_string(tok.type()).c_str(), tok.type(), tok.identifier())
10
11 #define TRACE_END2(tok) kwtrace_end(depth, "{}: {}", to_string(tok.type()).c_str(), tok.type())
12
13 #define TRACE_START() TRACE_START2(token())
14
15 #define TRACE_END() TRACE_END2(token())
16
17 #define MAYBE_COMMENT(obj, attr) \
18 if (token().type() == tok_comment) { \
19 (obj)->attr = parse_comment(parent, depth + 1); \
20 }
21
22 namespace lython {
23
24 #define SHOW_TOK(tok) kwerror("{}", str(tok));
25
26 // Reduce the number of dynamic alloc
27 // but debug info is not kept for the nodes
28 #define AVOID_DUPLICATE_CONST 0
29
30 template <typename Literal>
31 ExprNode* parse_literal(Parser* parser, Node* parent, ExprNode* child, char kind, int depth);
32
33 StmtNode* not_implemented_stmt(Node* parent) { return parent->new_object<NotImplementedStmt>(); }
34
35 ExprNode* not_implemented_expr(Node* parent) { return parent->new_object<NotImplementedExpr>(); }
36
37 ExprNode* not_allowed_expr(Node* parent) { return parent->new_object<NotAllowedEpxr>(); }
38
39 void Parser::start_code_loc(CommonAttributes* target, Token tok) {
40 7467 target->col_offset = tok.begin_col();
41 7467 target->lineno = tok.line();
42 7467 }
43 void Parser::end_code_loc(CommonAttributes* target, Token tok) {
44 6865 target->col_offset = tok.end_col();
45
1/1
✓ Branch 2 taken 6865 times.
6865 target->end_lineno = tok.line();
46 6865 }
47
48 #define PARSER_THROW(T, err) throw T(err.message)
49
50 // Helpers
51 // ---------------------------------------------
52
53 void Parser::ensure_valid() {
54 if (has_errors()) {
55 throw ParsingException();
56 }
57 }
58
59 void Parser::show_diagnostics(std::ostream& out) {
60 //
61
2/2
✓ Branch 1 taken 561 times.
✓ Branch 2 taken 393 times.
954 if (has_errors()) {
62
3/3
✓ Branch 1 taken 561 times.
✓ Branch 5 taken 561 times.
✓ Branch 8 taken 561 times.
561 out << "Parsing error messages (" << errors.size() << ")\n";
63
64 561 ParsingErrorPrinter printer(out, &_lex);
65 561 printer.with_compiler_code_loc = true;
66 561 printer.indent = 1;
67
68
2/2
✓ Branch 5 taken 565 times.
✓ Branch 6 taken 561 times.
1126 for (ParsingError const& error: errors) {
69
1/1
✓ Branch 1 taken 565 times.
565 out << " ";
70
1/1
✓ Branch 1 taken 565 times.
565 printer.print(error);
71
1/1
✓ Branch 1 taken 565 times.
565 out << "\n";
72 }
73 561 }
74 954 }
75
76 void Parser::expect_token(int expected, bool eat, Node* wip_expression, CodeLocation const& loc) {
77
2/2
✓ Branch 2 taken 9679 times.
✓ Branch 5 taken 9433 times.
9925 return expect_tokens(Array<int>{expected}, eat, wip_expression, loc);
78 }
79
80 OpConfig const& Parser::get_operator_config(Token const& tok) const {
81 static OpConfig nothing;
82
83
1/1
✓ Branch 1 taken 896 times.
896 Dict<String, OpConfig> const& confs = default_precedence();
84
85
1/1
✓ Branch 2 taken 896 times.
896 auto result = confs.find(tok.operator_name());
86
2/2
✓ Branch 2 taken 512 times.
✓ Branch 3 taken 384 times.
896 if (result == confs.end()) {
87 512 return nothing;
88 }
89 384 return result->second;
90 }
91
92 bool Parser::is_binary_operator_family(OpConfig const& conf) {
93
4/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 154 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 111 times.
353 return conf.binarykind != BinaryOperator::None || conf.cmpkind != CmpOperator::None ||
94
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
353 conf.boolkind != BoolOperator::None;
95 }
96
97 void Parser::expect_operator(String const& op,
98 bool eat,
99 Node* wip_expression,
100 CodeLocation const& loc) {
101 Token tok = token();
102
103 expect_token(tok_operator, eat, wip_expression, LOC);
104
105 if (tok.operator_name() == op) {
106 return;
107 }
108
109 ParsingError& error = parser_kwerror( //
110 loc, //
111 "SyntaxError", //
112 fmtstr("Wrong operator expected {} but got {}", op, tok.operator_name()) //
113 //
114 );
115
116 add_wip_expr(error, wip_expression);
117 PARSER_THROW(SyntaxError, error);
118 }
119
120 void Parser::expect_tokens(Array<int> const& expected,
121 bool eat,
122 Node* wip_expression,
123 CodeLocation const& loc) {
124
1/1
✓ Branch 1 taken 13917 times.
13917 auto toktype = token().type();
125
126
2/2
✓ Branch 5 taken 16820 times.
✓ Branch 6 taken 251 times.
17071 for (auto& tok: expected) {
127
2/2
✓ Branch 0 taken 13666 times.
✓ Branch 1 taken 3154 times.
16820 if (toktype == tok) {
128
2/2
✓ Branch 0 taken 13535 times.
✓ Branch 1 taken 131 times.
13666 if (eat) {
129
1/1
✓ Branch 1 taken 13535 times.
13535 next_token();
130 }
131 13666 return;
132 }
133 }
134 // ----
135 251 Array<String> expected_str;
136
1/1
✓ Branch 2 taken 251 times.
251 expected_str.reserve(expected.size());
137
2/2
✓ Branch 4 taken 256 times.
✓ Branch 5 taken 251 times.
507 for (auto& ex: expected) {
138
2/2
✓ Branch 1 taken 256 times.
✓ Branch 4 taken 256 times.
256 expected_str.push_back(str(TokenType(ex)));
139 }
140
141
2/2
✓ Branch 2 taken 251 times.
✓ Branch 5 taken 251 times.
251 ParsingError& error = parser_kwerror( //
142 loc, //
143 "SyntaxError", //
144
3/3
✓ Branch 2 taken 251 times.
✓ Branch 5 taken 251 times.
✓ Branch 8 taken 251 times.
753 fmtstr("Expected {} got {}", join(", ", expected), toktype) //
145 );
146
1/1
✓ Branch 1 taken 251 times.
251 error.expected_tokens = expected;
147
2/2
✓ Branch 1 taken 251 times.
✓ Branch 4 taken 251 times.
251 error.received_token = token();
148
149
1/1
✓ Branch 1 taken 251 times.
251 add_wip_expr(error, wip_expression);
150
1/1
✓ Branch 2 taken 251 times.
251 PARSER_THROW(SyntaxError, error);
151 251 }
152
153 Token Parser::parse_body(Node* parent, Array<StmtNode*>& out, int depth) {
154 TRACE_START();
155
156
4/4
✓ Branch 1 taken 4705 times.
✓ Branch 5 taken 4705 times.
✓ Branch 7 taken 2511 times.
✓ Branch 8 taken 2194 times.
4705 while (!in(token().type(), tok_desindent, tok_eof)) {
157
158 // Found an unexpected token
159 // eat the full line to try to recover and emit an error
160
2/3
✓ Branch 1 taken 2511 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2511 times.
2511 if (token().type() == tok_incorrect) {
161 ParsingError& error = parser_kwerror( //
162 LOC, //
163 "SyntaxError", //
164 "Unexpected token" //
165 );
166 add_wip_expr(error, parent);
167 error_recovery(&error);
168
169 InvalidStatement* stmt = parent->new_object<InvalidStatement>();
170 stmt->tokens = error.line;
171 out.push_back(stmt);
172 continue;
173 }
174
175 // Comment attach themselves to the next statement
176 // when comments are inserted at the beginning of a block
177 // they can be inserted to the previous block instead
178
3/3
✓ Branch 1 taken 2511 times.
✓ Branch 4 taken 116 times.
✓ Branch 5 taken 2395 times.
2511 if (token().type() == tok_comment) {
179
1/1
✓ Branch 1 taken 116 times.
116 StmtNode* cmt = parse_comment_stmt(parent, depth);
180
1/1
✓ Branch 1 taken 116 times.
116 _pending_comments.push_back(cmt);
181 116 continue;
182 116 }
183
184 // we have read a bunch of comments and we are still in this block
185 {
186
2/2
✓ Branch 5 taken 105 times.
✓ Branch 6 taken 2395 times.
2500 for (auto* comment: _pending_comments) {
187
1/1
✓ Branch 1 taken 105 times.
105 out.push_back(comment);
188 }
189 2395 _pending_comments.clear();
190 }
191
192 try {
193
1/1
✓ Branch 1 taken 1834 times.
2395 auto stmt = parse_statement(parent, depth + 1);
194
195 // only one liner should have the comment attached
196
8/8
✓ Branch 1 taken 1834 times.
✓ Branch 3 taken 982 times.
✓ Branch 4 taken 852 times.
✓ Branch 6 taken 982 times.
✓ Branch 9 taken 120 times.
✓ Branch 10 taken 862 times.
✓ Branch 11 taken 120 times.
✓ Branch 12 taken 1714 times.
1834 if (stmt->is_one_line() && token().type() == tok_comment) {
197
1/1
✓ Branch 1 taken 120 times.
120 stmt->comment = parse_comment(stmt, depth);
198 }
199
200
2/2
✓ Branch 0 taken 1776 times.
✓ Branch 1 taken 58 times.
1834 if (!is_empty_line) {
201 // expects at least one newline to end the statement
202 // if not we do not know what this line is supposed to be
203 expect_tokens({tok_newline, tok_eof}, true, parent, LOC);
204 }
205
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1830 times.
1830 if (stmt == nullptr) {
207 return token();
208 }
209
210
1/1
✓ Branch 1 taken 1830 times.
1830 out.push_back(stmt);
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 565 times.
565 } catch (ParsingException const&) {
212 //
213 565 ParsingError* error = &errors[current_error];
214
1/1
✓ Branch 1 taken 565 times.
565 error_recovery(error);
215
216
1/1
✓ Branch 1 taken 565 times.
565 InvalidStatement* stmt = parent->new_object<InvalidStatement>();
217
1/1
✓ Branch 1 taken 565 times.
565 stmt->tokens = error->line;
218
1/1
✓ Branch 1 taken 565 times.
565 out.push_back(stmt);
219 565 }
220
221 // look for the desindent token or next statement
222
3/3
✓ Branch 1 taken 2479 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 2395 times.
2479 while (token().type() == tok_newline) {
223
1/1
✓ Branch 1 taken 84 times.
84 next_token();
224 }
225 }
226
227
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 2164 times.
2194 if (out.size() <= 0) {
228
2/2
✓ Branch 2 taken 30 times.
✓ Branch 6 taken 30 times.
60 ParsingError& error = parser_kwerror( //
229 LOC, //
230 "SyntaxError", //
231 "Expected a body" //
232 );
233
1/1
✓ Branch 1 taken 30 times.
30 add_wip_expr(error, parent);
234
1/1
✓ Branch 2 taken 30 times.
30 PARSER_THROW(SyntaxError, error);
235 }
236
237
2/2
✓ Branch 1 taken 2164 times.
✓ Branch 4 taken 2164 times.
2164 auto last = token();
238
239
6/6
✓ Branch 1 taken 1797 times.
✓ Branch 2 taken 367 times.
✓ Branch 3 taken 1484 times.
✓ Branch 4 taken 313 times.
✓ Branch 5 taken 1484 times.
✓ Branch 6 taken 680 times.
2164 if (last.type() == tok_eof && depth == 0) {
240 // reached eof, insert all the comments here
241
2/2
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 1484 times.
1495 for (auto* comment: _pending_comments) {
242
1/1
✓ Branch 1 taken 11 times.
11 out.push_back(comment);
243 }
244 1484 _pending_comments.clear();
245 }
246 //
247 expect_tokens({tok_desindent, tok_eof}, true, parent, LOC);
248 2164 return last;
249 2164 }
250
251 bool Parser::is_tok_statement_ender() const {
252 // returns true if the token terminates a statement
253
2/2
✓ Branch 1 taken 508 times.
✓ Branch 5 taken 508 times.
508 return in(token().type(), tok_newline, tok_eof, tok_comment);
254 }
255
256 void Parser::expect_newline(Node* stmt, CodeLocation const& loc) {
257 921 expect_token(tok_newline, true, stmt, loc);
258
259
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 887 times.
888 while (token().type() == tok_newline) {
260 1 next_token();
261 }
262 887 }
263
264 // Statement_1
265 StmtNode* Parser::parse_function_def(Node* parent, bool async, int depth) {
266 TRACE_START();
267
268 216 FunctionDef* stmt = nullptr;
269
2/2
✓ Branch 1 taken 216 times.
✓ Branch 4 taken 216 times.
216 auto start = token();
270
1/1
✓ Branch 1 taken 216 times.
216 async_mode.push_back(async);
271
272
1/2
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
216 if (!async) {
273
1/1
✓ Branch 1 taken 216 times.
216 stmt = parent->new_object<FunctionDef>();
274 } else {
275 next_token(); // eat async
276 stmt = parent->new_object<AsyncFunctionDef>();
277 }
278
279
3/4
✓ Branch 1 taken 216 times.
✓ Branch 3 taken 216 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 216 times.
216 start_code_loc(stmt, start);
280
1/1
✓ Branch 1 taken 216 times.
216 next_token();
281
282
2/2
✓ Branch 1 taken 216 times.
✓ Branch 4 taken 216 times.
216 stmt->name = get_identifier();
283
284 expect_token(tok_identifier, true, stmt, LOC);
285 expect_token(tok_parens, true, stmt, LOC);
286
2/2
✓ Branch 1 taken 182 times.
✓ Branch 4 taken 182 times.
210 stmt->args = parse_arguments(stmt, ')', depth + 1);
287
288
3/3
✓ Branch 1 taken 182 times.
✓ Branch 4 taken 78 times.
✓ Branch 5 taken 104 times.
182 if (token().type() == tok_arrow) {
289
1/1
✓ Branch 1 taken 78 times.
78 next_token();
290
2/2
✓ Branch 1 taken 77 times.
✓ Branch 4 taken 77 times.
78 stmt->returns = parse_expression(stmt, depth + 1);
291 }
292
293 expect_token(':', true, stmt, LOC);
294 expect_comment_or_newline(stmt, depth, LOC);
295 expect_token(tok_indent, true, stmt, LOC);
296
297
3/3
✓ Branch 1 taken 170 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 160 times.
170 if (token().type() == tok_docstring) {
298 10 Comment* comment = nullptr;
299
2/2
✓ Branch 1 taken 10 times.
✓ Branch 5 taken 10 times.
10 String docstring = token().identifier();
300
301
1/1
✓ Branch 1 taken 10 times.
10 next_token();
302
3/3
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9 times.
10 if (token().type() == tok_comment) {
303
1/1
✓ Branch 1 taken 1 times.
1 comment = parse_comment(parent, depth + 1);
304 }
305
306
2/2
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 10 times.
10 stmt->docstring = Docstring(docstring, comment);
307 expect_newline(stmt, LOC);
308 10 }
309
310
1/1
✓ Branch 1 taken 165 times.
169 auto last = parse_body(stmt, stmt->body, depth + 1);
311
3/4
✓ Branch 1 taken 165 times.
✓ Branch 3 taken 165 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 165 times.
165 end_code_loc(stmt, last);
312 165 async_mode.pop_back();
313
314 TRACE_END();
315 165 return stmt;
316 216 }
317
318 StmtNode* Parser::parse_class_def(Node* parent, int depth) {
319 TRACE_START();
320
321
1/1
✓ Branch 1 taken 76 times.
76 auto stmt = parent->new_object<ClassDef>();
322
4/5
✓ Branch 1 taken 76 times.
✓ Branch 4 taken 76 times.
✓ Branch 6 taken 76 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 76 times.
76 start_code_loc(stmt, token());
323
1/1
✓ Branch 1 taken 76 times.
76 next_token();
324
325
2/2
✓ Branch 1 taken 76 times.
✓ Branch 4 taken 76 times.
76 stmt->name = get_identifier();
326 expect_token(tok_identifier, true, stmt, LOC);
327
328 // Parse bases
329
3/3
✓ Branch 1 taken 74 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 56 times.
74 if (token().type() == tok_parens) {
330
1/1
✓ Branch 1 taken 18 times.
18 next_token();
331
1/1
✓ Branch 1 taken 12 times.
18 parse_call_args(stmt, stmt->bases, stmt->keywords, depth + 1);
332 }
333
334 expect_token(':', true, stmt, LOC);
335 expect_comment_or_newline(stmt, depth, LOC);
336 expect_token(tok_indent, true, stmt, LOC);
337
338
3/3
✓ Branch 1 taken 61 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 53 times.
61 if (token().type() == tok_docstring) {
339 8 Comment* comment = nullptr;
340
2/2
✓ Branch 1 taken 8 times.
✓ Branch 5 taken 8 times.
8 String docstring = token().identifier();
341
1/1
✓ Branch 1 taken 8 times.
8 next_token();
342
343
3/3
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7 times.
8 if (token().type() == tok_comment) {
344
1/1
✓ Branch 1 taken 1 times.
1 comment = parse_comment(parent, depth + 1);
345 }
346
347
2/2
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
8 stmt->docstring = Docstring(docstring, comment);
348 expect_newline(stmt, LOC);
349 8 }
350
351
1/1
✓ Branch 1 taken 57 times.
60 auto last = parse_body(stmt, stmt->body, depth + 1);
352
353
2/2
✓ Branch 5 taken 135 times.
✓ Branch 6 taken 54 times.
189 for (auto child: stmt->body) {
354 // this checks we do not have expression inside the body of a class
355
1/1
✓ Branch 1 taken 135 times.
135 Expr* exprstmt = cast<Expr>(child);
356
357 // Comments are fine though
358
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
135 if (exprstmt && exprstmt->value->kind != NodeKind::Comment) {
359
2/2
✓ Branch 2 taken 3 times.
✓ Branch 6 taken 3 times.
6 ParsingError& error = parser_kwerror( //
360 LOC, //
361 "SyntaxError", //
362 "Unsupported statement inside a classdef" //
363 );
364
1/1
✓ Branch 1 taken 3 times.
3 add_wip_expr(error, parent);
365
1/1
✓ Branch 2 taken 3 times.
3 PARSER_THROW(SyntaxError, error);
366 }
367 }
368
369
3/4
✓ Branch 1 taken 54 times.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 54 times.
54 end_code_loc(stmt, last);
370 54 return stmt;
371 57 }
372 ExprNode* Parser::parse_star_expression(Node* parent, int depth) {
373 // star_expressions:
374 // | star_expression (',' star_expression )+ [',']
375 // | star_expression ','
376 // | star_expression
377 // star_expression:
378 // | '*' bitwise_or
379 // | expression
380 return parse_expression(parent, depth);
381 }
382
383 ExprNode* Parser::parse_star_targets(Node* parent, int depth) {
384
2/2
✓ Branch 1 taken 104 times.
✓ Branch 4 taken 104 times.
104 auto start_tok = token();
385
386 // auto kind = 0;
387 // bool has_parens = false;
388
2/3
✓ Branch 1 taken 104 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 104 times.
104 if (token().type() == tok_parens) {
389 next_token();
390 // kind = tok_parens;
391 // has_parens = true;
392 }
393
394 104 Array<ExprNode*> elts;
395
1/1
✓ Branch 1 taken 98 times.
104 auto r = parse_expression_primary(parent, depth + 1);
396
1/1
✓ Branch 1 taken 98 times.
98 elts.push_back(r);
397
398
3/3
✓ Branch 1 taken 126 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 92 times.
126 while (token().type() == tok_comma) {
399
1/1
✓ Branch 1 taken 34 times.
34 next_token();
400
2/2
✓ Branch 1 taken 28 times.
✓ Branch 4 taken 28 times.
34 elts.push_back(parse_expression_primary(parent, depth + 1));
401 };
402
403
2/2
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 14 times.
92 if (elts.size() == 1) {
404
3/4
✓ Branch 1 taken 78 times.
✓ Branch 4 taken 78 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 78 times.
78 start_code_loc(elts[0], start_tok);
405
4/5
✓ Branch 1 taken 78 times.
✓ Branch 4 taken 78 times.
✓ Branch 7 taken 78 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 78 times.
78 end_code_loc(elts[0], token());
406 78 return elts[0];
407 }
408
409
1/1
✓ Branch 1 taken 14 times.
14 auto expr = parent->new_object<TupleExpr>();
410
3/4
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 14 times.
14 start_code_loc(expr, start_tok);
411
1/1
✓ Branch 1 taken 14 times.
14 expr->elts = elts;
412 14 expr->ctx = ExprContext::Store;
413
4/5
✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 14 times.
14 end_code_loc(expr, token());
414 14 return expr;
415
416 // star_targets:
417 // | star_target !','
418 // | star_target (',' star_target )* [',']
419 // star_target:
420 // | '*' (!'*' star_target)
421 // | target_with_star_atom
422 // target_with_star_atom:
423 // | t_primary '.' NAME !t_lookahead
424 // | t_primary '[' slices ']' !t_lookahead
425 // | star_atom
426 // star_atom:
427 // | NAME
428 // | '(' target_with_star_atom ')'
429 // | '(' [star_targets_tuple_seq] ')'
430 // | '[' [star_targets_list_seq] ']'
431 // t_primary:
432 // | t_primary '.' NAME &t_lookahead
433 // | t_primary '[' slices ']' &t_lookahead
434 // | t_primary genexp &t_lookahead
435 // | t_primary '(' [arguments] ')' &t_lookahead
436 // | atom &t_lookahead
437 // t_lookahead: '(' | '[' | '.'
438 116 }
439
440 void Parser::expect_comment_or_newline(StmtNode* stmt, int depth, CodeLocation const& loc) {
441 533 add_inline_comment(stmt, depth);
442 533 expect_newline(stmt, loc);
443 517 }
444
445 StmtNode* Parser::parse_for(Node* parent, int depth) {
446 TRACE_START();
447
448 48 For* stmt = nullptr;
449
2/3
✓ Branch 1 taken 48 times.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
48 if (!async()) {
450
1/1
✓ Branch 1 taken 48 times.
48 stmt = parent->new_object<For>();
451 } else {
452 stmt = parent->new_object<AsyncFor>();
453 stmt->async = true;
454 }
455
456
4/5
✓ Branch 1 taken 48 times.
✓ Branch 4 taken 48 times.
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 48 times.
48 start_code_loc(stmt, token());
457
1/1
✓ Branch 1 taken 48 times.
48 next_token();
458
459 // Store context i.e the variables are created there
460
1/1
✓ Branch 1 taken 48 times.
48 _context.push_back(ExprContext::Store);
461
1/1
✓ Branch 1 taken 40 times.
48 stmt->target = parse_star_targets(stmt, depth + 1);
462 40 _context.pop_back();
463
464 // the right context was already picked up
465 // set_context(stmt->target, ExprContext::Store);
466
467 expect_token(tok_in, true, stmt, LOC);
468
1/1
✓ Branch 1 taken 34 times.
36 stmt->iter = parse_expression(stmt, depth + 1);
469
470 expect_token(':', true, parent, LOC);
471
472 expect_comment_or_newline(stmt, depth, LOC);
473 expect_token(tok_indent, true, parent, LOC);
474
475
1/1
✓ Branch 1 taken 26 times.
28 auto last = parse_body(stmt, stmt->body, depth + 1);
476
477
3/3
✓ Branch 1 taken 26 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 16 times.
26 if (token().type() == tok_else) {
478
1/1
✓ Branch 1 taken 10 times.
10 next_token();
479 expect_token(':', true, stmt, LOC);
480
481
4/4
✓ Branch 1 taken 9 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 8 times.
✓ Branch 7 taken 1 times.
9 MAYBE_COMMENT(stmt, else_comment);
482 expect_newline(stmt, LOC);
483
484 expect_token(tok_indent, true, stmt, LOC);
485
486
1/1
✓ Branch 1 taken 6 times.
7 last = parse_body(stmt, stmt->orelse, depth + 1);
487 }
488
489
3/4
✓ Branch 1 taken 22 times.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22 times.
22 end_code_loc(stmt, last);
490 22 return stmt;
491 26 }
492
493 StmtNode* Parser::parse_while(Node* parent, int depth) {
494 TRACE_START();
495
496
1/1
✓ Branch 1 taken 25 times.
25 auto stmt = parent->new_object<While>();
497
4/5
✓ Branch 1 taken 25 times.
✓ Branch 4 taken 25 times.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 25 times.
25 start_code_loc(stmt, token());
498
1/1
✓ Branch 1 taken 25 times.
25 next_token();
499
500
1/1
✓ Branch 1 taken 24 times.
25 stmt->test = parse_expression(stmt, depth + 1);
501 expect_token(':', true, stmt, LOC);
502 expect_comment_or_newline(stmt, depth, LOC);
503 expect_token(tok_indent, true, stmt, LOC);
504
505
1/1
✓ Branch 1 taken 20 times.
21 auto last = parse_body(stmt, stmt->body, depth + 1);
506
507
3/3
✓ Branch 1 taken 20 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 9 times.
20 if (token().type() == tok_else) {
508
1/1
✓ Branch 1 taken 11 times.
11 next_token();
509 expect_token(':', true, stmt, LOC);
510
511
4/4
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9 times.
✓ Branch 7 taken 1 times.
10 MAYBE_COMMENT(stmt, else_comment);
512 expect_newline(stmt, LOC);
513
514 expect_token(tok_indent, true, stmt, LOC);
515
1/1
✓ Branch 1 taken 7 times.
8 last = parse_body(stmt, stmt->orelse, depth + 1);
516 }
517
518
3/4
✓ Branch 1 taken 16 times.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
16 end_code_loc(stmt, last);
519 16 return stmt;
520 20 }
521
522 StmtNode* Parser::parse_if_alt(Node* parent, int depth) {
523 TRACE_START();
524
525
1/1
✓ Branch 1 taken 33 times.
33 auto stmt = parent->new_object<If>();
526
4/5
✓ Branch 1 taken 33 times.
✓ Branch 4 taken 33 times.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 33 times.
33 start_code_loc(stmt, token());
527
1/1
✓ Branch 1 taken 33 times.
33 next_token();
528
1/1
✓ Branch 2 taken 33 times.
33 Token last = dummy();
529
530 // Parse first If
531 {
532
1/1
✓ Branch 1 taken 32 times.
33 stmt->test = parse_expression(stmt, depth + 1);
533
534 expect_token(':', true, stmt, LOC);
535 expect_comment_or_newline(stmt, depth, LOC);
536 expect_token(tok_indent, true, stmt, LOC);
537
538
1/1
✓ Branch 1 taken 28 times.
29 auto last = parse_body(stmt, stmt->body, depth + 1);
539 28 }
540
541
3/3
✓ Branch 1 taken 42 times.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 23 times.
42 while (token().type() == tok_elif) {
542
1/1
✓ Branch 1 taken 19 times.
19 next_token();
543
544
1/1
✓ Branch 1 taken 18 times.
19 auto test = parse_expression(stmt, depth + 1);
545 expect_token(':', true, stmt, LOC);
546
547 // We need to push a comment even if there is nothing
548 // because we will zip between tests and tests_comments
549 17 int n = int(stmt->tests_comment.size());
550
1/1
✓ Branch 1 taken 17 times.
17 stmt->tests_comment.push_back(nullptr);
551
552
4/4
✓ Branch 1 taken 17 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 16 times.
✓ Branch 7 taken 1 times.
17 MAYBE_COMMENT(stmt, tests_comment[n]);
553 expect_newline(stmt, LOC);
554 expect_token(tok_indent, true, stmt, LOC);
555
556 15 Array<StmtNode*> body;
557
1/1
✓ Branch 1 taken 14 times.
15 last = parse_body(stmt, body, depth + 1);
558
559
1/1
✓ Branch 1 taken 14 times.
14 stmt->tests.push_back(test);
560
1/1
✓ Branch 1 taken 14 times.
14 stmt->bodies.push_back(body);
561 15 }
562
563 // The else belongs to the last ifexpr if any
564
3/3
✓ Branch 1 taken 23 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 10 times.
23 if (token().type() == tok_else) {
565
1/1
✓ Branch 1 taken 13 times.
13 next_token();
566
567 expect_token(':', true, stmt, LOC);
568
569
4/4
✓ Branch 1 taken 12 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 11 times.
✓ Branch 7 taken 1 times.
12 MAYBE_COMMENT(stmt, else_comment);
570 expect_newline(stmt, LOC);
571
572 expect_token(tok_indent, true, stmt, LOC);
573
574
1/1
✓ Branch 1 taken 9 times.
10 last = parse_body(stmt, stmt->orelse, depth + 1);
575 }
576
577
3/4
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 19 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 19 times.
19 end_code_loc(stmt, last);
578 19 return stmt;
579 33 }
580
581 StmtNode* Parser::parse_if(Node* parent, int depth) {
582 TRACE_START();
583
584 auto stmt = parent->new_object<If>();
585 start_code_loc(stmt, token());
586 next_token();
587
588 stmt->test = parse_expression(stmt, depth + 1);
589
590 expect_token(':', true, stmt, LOC);
591 expect_comment_or_newline(stmt, depth, LOC);
592 expect_token(tok_indent, true, stmt, LOC);
593
594 auto last = parse_body(stmt, stmt->body, depth + 1);
595
596 // The else belongs to the last if if any
597 if (token().type() == tok_else) {
598 next_token();
599
600 expect_token(':', true, stmt, LOC);
601
602 MAYBE_COMMENT(stmt, else_comment);
603 expect_newline(stmt, LOC);
604
605 expect_token(tok_indent, true, stmt, LOC);
606
607 last = parse_body(stmt, stmt->orelse, depth + 1);
608 }
609
610 // This is interesting looks like python does not chain ifs in the AST
611 if (token().type() == tok_elif) {
612 auto elseif = parse_if(stmt, depth + 1);
613 stmt->orelse.push_back(elseif);
614 }
615
616 end_code_loc(stmt, last);
617 return stmt;
618 }
619
620 // [<pattern>, <pattern>, ...]
621 Pattern* Parser::parse_match_sequence(Node* parent, int depth) {
622 TRACE_START();
623
624 111 auto pat = parent->new_object<MatchSequence>();
625
4/5
✓ Branch 1 taken 111 times.
✓ Branch 4 taken 111 times.
✓ Branch 6 taken 111 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 111 times.
111 start_code_loc(pat, token());
626 111 next_token();
627
628
2/2
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 24 times.
193 while (token().type() != ']') {
629
1/1
✓ Branch 1 taken 163 times.
169 auto child = parse_pattern(pat, depth + 1);
630
1/1
✓ Branch 1 taken 163 times.
163 pat->patterns.push_back(child);
631
632
3/3
✓ Branch 1 taken 163 times.
✓ Branch 4 taken 82 times.
✓ Branch 5 taken 81 times.
163 if (token().type() == tok_comma) {
633
1/1
✓ Branch 1 taken 82 times.
82 next_token();
634 } else {
635 81 break;
636 }
637 }
638
639
4/5
✓ Branch 1 taken 105 times.
✓ Branch 4 taken 105 times.
✓ Branch 6 taken 105 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 105 times.
105 end_code_loc(pat, token());
640 expect_token(']', true, pat, LOC);
641 TRACE_END();
642 101 return pat;
643 }
644
645 // *<identifier>
646 Pattern* Parser::parse_match_star(Node* parent, int depth) {
647 TRACE_START();
648
649 13 auto pat = parent->new_object<MatchStar>();
650
4/5
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 13 times.
13 start_code_loc(pat, token());
651 13 next_token();
652
653
3/3
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
✓ Branch 7 taken 13 times.
13 pat->name = get_identifier();
654 expect_token(tok_identifier, true, pat, LOC);
655
656
4/5
✓ Branch 1 taken 12 times.
✓ Branch 4 taken 12 times.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 12 times.
12 end_code_loc(pat, token());
657 12 return pat;
658 }
659
660 // <expr>(<pattern>..., <identifier>=<pattern>)
661 Pattern* Parser::parse_match_class(Node* parent, ExprNode* cls, int depth) {
662 TRACE_START();
663
664 35 auto pat = parent->new_object<MatchClass>();
665 35 pat->cls = cls;
666
667 // TODO: This is the location of '(' not the full pattern
668
4/5
✓ Branch 1 taken 35 times.
✓ Branch 4 taken 35 times.
✓ Branch 6 taken 35 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 35 times.
35 start_code_loc(pat, token());
669 expect_token(tok_parens, true, pat, LOC);
670
671 35 bool keyword = false;
672
1/2
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
99 while (token().type() != ')') {
673
674 // keyword arguments are starting
675
6/6
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 3 times.
✓ Branch 6 taken 29 times.
✓ Branch 7 taken 67 times.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 70 times.
99 if (token().type() == tok_identifier && peek_token().type() == tok_assign) {
676 29 keyword = true;
677 }
678
679 // positional arguments
680
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 29 times.
99 if (!keyword) {
681
2/2
✓ Branch 1 taken 67 times.
✓ Branch 4 taken 67 times.
70 pat->patterns.push_back(parse_pattern(pat, depth + 1));
682 }
683
684 // keywords
685
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 else if (keyword) {
686
3/3
✓ Branch 1 taken 29 times.
✓ Branch 4 taken 29 times.
✓ Branch 7 taken 29 times.
29 pat->kwd_attrs.push_back(get_identifier());
687 expect_token(tok_identifier, true, pat, LOC);
688 expect_token(tok_assign, true, pat, LOC);
689
2/2
✓ Branch 1 taken 28 times.
✓ Branch 4 taken 28 times.
29 pat->kwd_patterns.push_back(parse_pattern(pat, depth + 1));
690 }
691
692
2/2
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 31 times.
95 if (token().type() == tok_comma) {
693 64 next_token();
694 } else {
695
4/5
✓ Branch 1 taken 31 times.
✓ Branch 4 taken 31 times.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 31 times.
31 end_code_loc(pat, token());
696 expect_token(')', true, pat, LOC);
697 27 break;
698 }
699 }
700
701 27 return pat;
702 }
703
704 // This one does not make much sense
705 // {'a': Point(x, y)}
706 // { 1 + 1: 2}
707 // { <expr>: <pattern> }
708 Pattern* Parser::parse_match_mapping(Node* parent, int depth) {
709 TRACE_START();
710
711 45 auto pat = parent->new_object<MatchMapping>();
712
4/5
✓ Branch 1 taken 45 times.
✓ Branch 4 taken 45 times.
✓ Branch 6 taken 45 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 45 times.
45 start_code_loc(pat, token());
713 45 next_token();
714
715
2/2
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 26 times.
59 while (token().type() != '}') {
716
717
3/3
✓ Branch 1 taken 33 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 20 times.
33 if (token().operator_name() == "**") {
718
1/1
✓ Branch 1 taken 13 times.
13 next_token();
719
3/3
✓ Branch 1 taken 13 times.
✓ Branch 5 taken 13 times.
✓ Branch 8 taken 13 times.
13 pat->rest = token().identifier();
720 expect_token(tok_identifier, true, pat, LOC);
721 13 break;
722 }
723
724
1/1
✓ Branch 1 taken 17 times.
20 auto key = parse_expression(pat, depth + 1);
725
726 expect_token(':', true, pat, LOC);
727
1/1
✓ Branch 1 taken 15 times.
16 auto child = parse_pattern(pat, depth + 1);
728
729
1/1
✓ Branch 1 taken 15 times.
15 pat->keys.push_back(key);
730
1/1
✓ Branch 1 taken 15 times.
15 pat->patterns.push_back(child);
731
732
3/3
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 1 times.
15 if (token().type() == tok_comma) {
733
1/1
✓ Branch 1 taken 14 times.
14 next_token();
734 } else {
735 1 break;
736 }
737 }
738
739
4/5
✓ Branch 1 taken 39 times.
✓ Branch 4 taken 39 times.
✓ Branch 6 taken 39 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 39 times.
39 end_code_loc(pat, token());
740 expect_token('}', true, pat, LOC);
741 37 return pat;
742 }
743
744 // <pattern> | <pattern> | ...
745 Pattern* Parser::parse_match_or(Node* parent, Pattern* child, int depth) {
746 TRACE_START();
747
748 46 auto pat = parent->new_object<MatchOr>();
749 46 pat->patterns.push_back(child);
750
751 // TODO: this is the loc of '|' not the start of the expression
752
4/5
✓ Branch 1 taken 46 times.
✓ Branch 4 taken 46 times.
✓ Branch 6 taken 46 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 46 times.
46 start_code_loc(pat, token());
753
754
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
46 if (token().operator_name() != "|") {
755 kwerror("Unexpected operator {}", token().operator_name());
756 }
757
758 46 next_token();
759
760
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
46 while (token().type() != ':') {
761 46 child = parse_pattern(pat, depth + 1);
762 45 pat->patterns.push_back(child);
763
764
2/6
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 45 times.
45 if (token().type() == tok_operator && token().operator_name() == "|") {
765 next_token();
766 } else {
767 // could be ":" or "if"
768 // expect_token(':', false, pat, LOC);
769 45 break;
770 }
771 }
772
773
4/5
✓ Branch 1 taken 45 times.
✓ Branch 4 taken 45 times.
✓ Branch 6 taken 45 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 45 times.
45 end_code_loc(pat, token());
774 45 return pat;
775 }
776
777 // <pattern> as <identifier>
778 Pattern* Parser::parse_match_as(Node* parent, Pattern* primary, int depth) {
779 TRACE_START();
780
781 57 auto pat = parent->new_object<MatchAs>();
782 57 pat->pattern = primary;
783
784 // TODO: this is the loc of 'as' not the start of the expression
785
4/5
✓ Branch 1 taken 57 times.
✓ Branch 4 taken 57 times.
✓ Branch 6 taken 57 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 57 times.
57 start_code_loc(pat, token());
786
787 expect_token(tok_as, true, pat, LOC);
788
3/3
✓ Branch 1 taken 57 times.
✓ Branch 4 taken 57 times.
✓ Branch 7 taken 57 times.
57 pat->name = get_identifier();
789
790
4/5
✓ Branch 1 taken 57 times.
✓ Branch 4 taken 57 times.
✓ Branch 6 taken 57 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 57 times.
57 end_code_loc(pat, token());
791 expect_token(tok_identifier, true, pat, LOC);
792
793 56 return pat;
794 }
795
796 Pattern* Parser::parse_pattern_1(Node* parent, int depth) {
797
798
5/5
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 45 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 136 times.
✓ Branch 6 taken 347 times.
652 switch (token().type()) {
799 111 case tok_square: return parse_match_sequence(parent, depth);
800
801 // TODO: make sure those are correct
802 45 case tok_curly: return parse_match_mapping(parent, depth);
803
804 13 case tok_operator:
805 case tok_star:
806
3/6
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 11 not taken.
13 if (token().operator_name() == "**" || token().operator_name() == "*") {
807 13 return parse_match_star(parent, depth);
808 }
809
810 // Constants
811 // The values represented can be simple types such as a number, string or None,
812 // but also immutable container types (tuples and frozensets)
813 // if all of their elements are constant.
814 case tok_int:
815 case tok_string:
816 case tok_float: {
817 136 auto pat = parent->new_object<MatchSingleton>();
818
2/2
✓ Branch 1 taken 136 times.
✓ Branch 4 taken 136 times.
136 pat->value = get_value(pat);
819 136 next_token();
820 136 return pat;
821 }
822
823 // case tok_identifier: return parse_match_class(parent, depth);
824 // MatchClass is expecting a expression not an identifier
825 // this is interesting does that mean if I call a function returning a type
826 // it will match on that type ?
827
828 // Value
829 347 default: {
830 // in this context we are storing components inside the pattern
831 //_context.push_back(ExprContext::Store);
832 347 auto value = parse_expression_primary(parent, depth + 1);
833 //_context.pop_back();
834 327 Pattern* pat = nullptr;
835
836 // <expr> if|:
837
2/2
✓ Branch 2 taken 292 times.
✓ Branch 3 taken 35 times.
327 if (token().type() != '(') {
838 292 pat = parent->new_object<MatchValue>();
839 292 ((MatchValue*)pat)->value = value;
840 292 set_context(value, ExprContext::Store);
841 } else {
842 35 pat = parse_match_class(parent, value, depth + 1);
843 }
844 319 value->move(pat);
845 319 return pat;
846 }
847 }
848 }
849
850 Pattern* Parser::parse_pattern(Node* parent, int depth) {
851 TRACE_START();
852
853 652 auto primary = parse_pattern_1(parent, depth);
854
855
3/3
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 502 times.
605 switch (token().type()) {
856 46 case tok_operator:
857 case '|':
858
1/2
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
46 if (token().operator_name() == "|") {
859 46 return parse_match_or(parent, primary, depth);
860 }
861
862 57 case tok_as: return parse_match_as(parent, primary, depth);
863 }
864 // could be ":" or "if"
865 // expect_token(':', false, primary, LOC);
866 502 return primary;
867 }
868
869 Token Parser::parse_match_case(Node* parent, Array<MatchCase>& out, int depth) {
870 TRACE_START();
871
872 129 Token last = token();
873
874
2/3
✓ Branch 1 taken 325 times.
✓ Branch 4 taken 325 times.
✗ Branch 5 not taken.
325 while (token().type() != tok_desindent) {
875
1/1
✓ Branch 1 taken 325 times.
325 MatchCase case_;
876 expect_token(tok_case, true, parent, LOC);
877 // Patern
878
1/1
✓ Branch 1 taken 285 times.
322 case_.pattern = parse_pattern(parent, depth);
879
880 // Guard
881
3/3
✓ Branch 1 taken 285 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 272 times.
285 if (token().type() == tok_if) {
882
1/1
✓ Branch 1 taken 13 times.
13 next_token();
883
2/2
✓ Branch 1 taken 12 times.
✓ Branch 4 taken 12 times.
13 case_.guard = parse_expression(parent, depth + 1);
884 }
885
886 expect_token(':', true, parent, LOC);
887
4/4
✓ Branch 1 taken 271 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 262 times.
✓ Branch 7 taken 9 times.
271 MAYBE_COMMENT(&case_, comment);
888 expect_newline(parent, LOC);
889 expect_token(tok_indent, true, parent, LOC);
890
891 // Branch
892
1/1
✓ Branch 1 taken 244 times.
253 last = parse_body(parent, case_.body, depth + 1);
893
1/1
✓ Branch 1 taken 244 times.
244 out.push_back(case_);
894
895 // Stop if next token is not for another branch
896
3/3
✓ Branch 1 taken 244 times.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 196 times.
244 if (token().type() != tok_case) {
897 expect_tokens({tok_desindent, tok_eof}, false, parent, LOC);
898 48 break;
899 }
900 325 }
901
902 48 return last;
903 81 }
904
905 StmtNode* Parser::parse_match(Node* parent, int depth) {
906 TRACE_START();
907
908
1/1
✓ Branch 1 taken 141 times.
141 auto stmt = parent->new_object<Match>();
909
4/5
✓ Branch 1 taken 141 times.
✓ Branch 4 taken 141 times.
✓ Branch 6 taken 141 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 141 times.
141 start_code_loc(stmt, token());
910
1/1
✓ Branch 1 taken 141 times.
141 next_token();
911
912
1/1
✓ Branch 1 taken 138 times.
141 stmt->subject = parse_expression(stmt, depth + 1);
913 expect_token(':', true, stmt, LOC);
914 expect_comment_or_newline(stmt, depth, LOC);
915 expect_token(tok_indent, true, parent, LOC);
916
917
1/1
✓ Branch 1 taken 48 times.
129 auto last = parse_match_case(stmt, stmt->cases, depth);
918
919 expect_tokens({tok_desindent, tok_eof}, true, stmt, LOC);
920
3/4
✓ Branch 1 taken 48 times.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 48 times.
48 end_code_loc(stmt, last);
921 TRACE_END();
922 48 return stmt;
923 48 }
924
925 void Parser::parse_withitem(Node* parent, Array<WithItem>& out, int depth) {
926 TRACE_START();
927
928
1/2
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
96 while (token().type() != ':') {
929
1/1
✓ Branch 1 taken 92 times.
96 ExprNode* expr = parse_expression(parent, depth + 1);
930 92 ExprNode* var = nullptr;
931
932
3/3
✓ Branch 1 taken 92 times.
✓ Branch 4 taken 88 times.
✓ Branch 5 taken 4 times.
92 if (token().type() == tok_as) {
933
1/1
✓ Branch 1 taken 88 times.
88 next_token();
934
1/1
✓ Branch 1 taken 84 times.
88 var = parse_expression_primary(parent, depth + 1);
935 }
936
937
1/1
✓ Branch 1 taken 88 times.
88 out.push_back(WithItem{expr, var});
938
939
3/3
✓ Branch 1 taken 88 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 44 times.
88 if (token().type() == tok_comma) {
940
1/1
✓ Branch 1 taken 44 times.
44 next_token();
941 } else {
942 44 break;
943 }
944 }
945 132 }
946
947 StmtNode* Parser::parse_with(Node* parent, int depth) {
948 TRACE_START();
949
950 52 With* stmt = nullptr;
951
2/3
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 52 times.
✗ Branch 4 not taken.
52 if (!async()) {
952
1/1
✓ Branch 1 taken 52 times.
52 stmt = parent->new_object<With>();
953 } else {
954 stmt = parent->new_object<AsyncWith>();
955 stmt->async = true;
956 }
957
958
4/5
✓ Branch 1 taken 52 times.
✓ Branch 4 taken 52 times.
✓ Branch 6 taken 52 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 52 times.
52 start_code_loc(stmt, token());
959
1/1
✓ Branch 1 taken 52 times.
52 next_token();
960
961
1/1
✓ Branch 1 taken 44 times.
52 parse_withitem(stmt, stmt->items, depth + 1);
962
963 expect_token(':', true, stmt, LOC);
964 expect_comment_or_newline(stmt, depth, LOC);
965 expect_token(tok_indent, true, stmt, LOC);
966
967
1/1
✓ Branch 1 taken 30 times.
32 auto last = parse_body(stmt, stmt->body, depth + 1);
968
4/5
✓ Branch 1 taken 30 times.
✓ Branch 4 taken 30 times.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 30 times.
30 end_code_loc(stmt, token());
969
970 30 return stmt;
971 30 }
972
973 StmtNode* Parser::parse_raise(Node* parent, int depth) {
974 TRACE_START();
975
976 16 auto stmt = parent->new_object<Raise>();
977
4/5
✓ Branch 1 taken 16 times.
✓ Branch 4 taken 16 times.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 16 times.
16 start_code_loc(stmt, token());
978 16 next_token();
979
980
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 2 times.
16 if (!is_tok_statement_ender()) {
981
2/2
✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
14 stmt->exc = parse_expression(stmt, depth + 1);
982
983
2/2
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
14 if (token().type() == tok_from) {
984 7 next_token();
985
2/2
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
7 stmt->cause = parse_expression(stmt, depth + 1);
986 }
987
988
4/5
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 13 times.
13 end_code_loc(stmt, token());
989 } else {
990
4/5
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
2 end_code_loc(stmt, token());
991
992
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (token().type() != tok_comment) {
993 2 next_token();
994 }
995 }
996
997 15 return stmt;
998 }
999
1000 Token Parser::parse_except_handler(Try* parent, Array<ExceptHandler>& out, int depth) {
1001 TRACE_START();
1002
1003
2/2
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 21 times.
49 while (token().type() == tok_except) {
1004
1/1
✓ Branch 1 taken 28 times.
28 next_token();
1005
1/1
✓ Branch 1 taken 28 times.
28 ExceptHandler handler;
1006
1007
2/3
✓ Branch 1 taken 28 times.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 if (token().type() != ':') {
1008
2/2
✓ Branch 1 taken 27 times.
✓ Branch 4 taken 27 times.
28 handler.type = parse_expression(parent, depth + 1);
1009
1010
3/3
✓ Branch 1 taken 27 times.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 1 times.
27 if (token().type() == tok_as) {
1011
1/1
✓ Branch 1 taken 26 times.
26 next_token();
1012
3/3
✓ Branch 1 taken 26 times.
✓ Branch 4 taken 26 times.
✓ Branch 7 taken 26 times.
26 handler.name = get_identifier();
1013 expect_token(tok_identifier, true, parent, LOC);
1014 }
1015 }
1016
1017 expect_token(':', true, parent, LOC);
1018
1/1
✓ Branch 1 taken 24 times.
24 add_inline_comment(parent, &handler, depth);
1019 expect_newline(parent, LOC);
1020 expect_token(tok_indent, true, parent, LOC);
1021
1022
1/1
✓ Branch 1 taken 21 times.
22 parse_body(parent, handler.body, depth + 1);
1023
1024
1/1
✓ Branch 1 taken 21 times.
21 out.push_back(handler);
1025 28 };
1026
1027 21 return token();
1028 }
1029
1030 StmtNode* Parser::parse_try(Node* parent, int depth) {
1031 TRACE_START();
1032
1033
1/1
✓ Branch 1 taken 35 times.
35 auto stmt = parent->new_object<Try>();
1034
4/5
✓ Branch 1 taken 35 times.
✓ Branch 4 taken 35 times.
✓ Branch 6 taken 35 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 35 times.
35 start_code_loc(stmt, token());
1035
1/1
✓ Branch 1 taken 35 times.
35 next_token();
1036
1037 expect_token(':', true, stmt, LOC);
1038 expect_comment_or_newline(stmt, depth, LOC);
1039 expect_token(tok_indent, true, stmt, LOC);
1040
1041
1/1
✓ Branch 1 taken 31 times.
32 auto last = parse_body(stmt, stmt->body, depth + 1);
1042
1043 expect_token(tok_except, false, stmt, LOC);
1044
1/1
✓ Branch 1 taken 21 times.
28 parse_except_handler(stmt, stmt->handlers, depth + 1);
1045
1046
3/3
✓ Branch 1 taken 21 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 3 times.
21 if (token().type() == tok_else) {
1047
1/1
✓ Branch 1 taken 18 times.
18 next_token(); // else
1048 expect_token(':', true, stmt, LOC);
1049
1050
4/4
✓ Branch 1 taken 17 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 16 times.
✓ Branch 7 taken 1 times.
17 MAYBE_COMMENT(stmt, else_comment);
1051 expect_newline(stmt, LOC);
1052
1053 expect_token(tok_indent, true, stmt, LOC);
1054
1/1
✓ Branch 1 taken 14 times.
15 parse_body(stmt, stmt->orelse, depth + 1);
1055 }
1056
1057
3/3
✓ Branch 1 taken 17 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 6 times.
17 if (token().type() == tok_finally) {
1058
1/1
✓ Branch 1 taken 11 times.
11 next_token(); // finally
1059 expect_token(':', true, stmt, LOC);
1060
1061
4/4
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9 times.
✓ Branch 7 taken 1 times.
10 MAYBE_COMMENT(stmt, finally_comment);
1062 expect_newline(stmt, LOC);
1063
1064 expect_token(tok_indent, true, stmt, LOC);
1065
1/1
✓ Branch 1 taken 7 times.
8 parse_body(stmt, stmt->finalbody, depth + 1);
1066 }
1067
1068
4/5
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 13 times.
13 end_code_loc(stmt, token());
1069 13 return stmt;
1070 31 }
1071
1072 StmtNode* Parser::parse_assert(Node* parent, int depth) {
1073 TRACE_START();
1074
1075 20 auto stmt = parent->new_object<Assert>();
1076
4/5
✓ Branch 1 taken 20 times.
✓ Branch 4 taken 20 times.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 20 times.
20 start_code_loc(stmt, token());
1077 20 next_token();
1078
1079 //
1080 20 stmt->test = parse_expression(stmt, depth + 1);
1081 //
1082
1083
2/2
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 7 times.
18 if (token().type() == tok_comma) {
1084 11 next_token();
1085
2/2
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 10 times.
11 stmt->msg = parse_expression(stmt, depth + 1);
1086 }
1087
1088
4/5
✓ Branch 1 taken 17 times.
✓ Branch 4 taken 17 times.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 17 times.
17 end_code_loc(stmt, token());
1089 17 return stmt;
1090 }
1091
1092 bool is_dot(Token const& tok) {
1093
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 438 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 43 times.
✓ Branch 9 taken 395 times.
438 return (tok.type() == tok_operator && tok.operator_name() == ".") || tok.type() == tok_dot;
1094 }
1095
1096 String Parser::parse_module_path(Node* parent, int& level, int depth) {
1097 179 level = 0;
1098 179 Array<String> path;
1099 179 bool last_was_dot = false;
1100
1101 // import <path> as adasd
1102 // from <path> import cd as xyz
1103
1104 while (true) {
1105 // relative path
1106
4/8
✓ Branch 1 taken 219 times.
✓ Branch 4 taken 219 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 219 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 219 times.
219 if (is_dot(token()) && path.size() <= 0) {
1107 level += 1;
1108 next_token();
1109 }
1110
1111 // module name
1112
3/3
✓ Branch 1 taken 219 times.
✓ Branch 4 taken 217 times.
✓ Branch 5 taken 2 times.
219 if (token().type() == tok_identifier) {
1113
2/2
✓ Branch 1 taken 217 times.
✓ Branch 4 taken 217 times.
217 path.push_back(get_identifier());
1114
1/1
✓ Branch 1 taken 217 times.
217 next_token();
1115 }
1116
1117 // separator
1118
4/4
✓ Branch 1 taken 219 times.
✓ Branch 4 taken 219 times.
✓ Branch 6 taken 43 times.
✓ Branch 7 taken 176 times.
219 if (is_dot(token())) {
1119
1/1
✓ Branch 1 taken 43 times.
43 next_token();
1120
1121 // need an identifier after a `.`
1122
3/3
✓ Branch 1 taken 43 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 40 times.
43 if (token().type() != tok_identifier) {
1123
2/2
✓ Branch 2 taken 3 times.
✓ Branch 6 taken 3 times.
6 ParsingError& error = parser_kwerror( //
1124 LOC, //
1125 "SyntaxError", //
1126 "expect name after ." //
1127 );
1128
1/1
✓ Branch 1 taken 3 times.
3 add_wip_expr(error, parent);
1129
1/1
✓ Branch 2 taken 3 times.
3 PARSER_THROW(SyntaxError, error);
1130 }
1131 }
1132
1133 // we have reached the en dof the path
1134
4/4
✓ Branch 1 taken 216 times.
✓ Branch 5 taken 216 times.
✓ Branch 7 taken 175 times.
✓ Branch 8 taken 41 times.
216 if (in(token().type(), tok_import, tok_as, tok_newline, tok_eof)) {
1135 175 break;
1136 }
1137
1138 //
1139 expect_tokens({tok_dot, tok_identifier}, false, parent, LOC);
1140 40 }
1141
1142
2/2
✓ Branch 2 taken 175 times.
✓ Branch 5 taken 175 times.
350 return join(".", path);
1143 179 }
1144
1145 void Parser::parse_alias(Node* parent, Array<Alias>& out, int depth) {
1146 TRACE_START();
1147
1148
2/2
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 4 times.
139 while (!is_tok_statement_ender()) {
1149
1/1
✓ Branch 1 taken 135 times.
135 Alias alias;
1150
1151 135 int level = 0;
1152
2/2
✓ Branch 1 taken 132 times.
✓ Branch 4 taken 132 times.
135 alias.name = parse_module_path(parent, level, depth);
1153
1154
3/3
✓ Branch 1 taken 132 times.
✓ Branch 4 taken 119 times.
✓ Branch 5 taken 13 times.
132 if (token().type() == tok_as) {
1155
1/1
✓ Branch 1 taken 119 times.
119 next_token();
1156
3/3
✓ Branch 1 taken 119 times.
✓ Branch 4 taken 119 times.
✓ Branch 7 taken 119 times.
119 alias.asname = get_identifier();
1157 expect_token(tok_identifier, true, parent, LOC);
1158 }
1159
1160
1/1
✓ Branch 1 taken 122 times.
122 out.push_back(alias);
1161
1162
3/3
✓ Branch 1 taken 122 times.
✓ Branch 4 taken 77 times.
✓ Branch 5 taken 45 times.
122 if (token().type() == ',') {
1163
1/1
✓ Branch 1 taken 77 times.
77 next_token();
1164
3/3
✓ Branch 1 taken 77 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 71 times.
77 if (token().type() != tok_identifier) {
1165
2/2
✓ Branch 2 taken 6 times.
✓ Branch 6 taken 6 times.
12 ParsingError& error = parser_kwerror( //
1166 LOC, //
1167 "SyntaxError", //
1168 "Expect identifier after ," //
1169 );
1170
1/1
✓ Branch 1 taken 6 times.
6 add_wip_expr(error, parent);
1171
1/1
✓ Branch 2 taken 6 times.
6 PARSER_THROW(SyntaxError, error);
1172 }
1173 } else {
1174 45 break;
1175 }
1176 135 }
1177
1178
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 45 times.
49 if (out.size() <= 0) {
1179
2/2
✓ Branch 2 taken 4 times.
✓ Branch 6 taken 4 times.
8 ParsingError& error = parser_kwerror( //
1180 LOC, //
1181 "SyntaxError", //
1182 "Expect packages" //
1183 );
1184 4 add_wip_expr(error, parent);
1185
1/1
✓ Branch 2 taken 4 times.
4 PARSER_THROW(SyntaxError, error);
1186 }
1187 45 }
1188
1189 StmtNode* Parser::parse_import(Node* parent, int depth) {
1190 TRACE_START();
1191
1192 30 auto stmt = parent->new_object<Import>();
1193
4/5
✓ Branch 1 taken 30 times.
✓ Branch 4 taken 30 times.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 30 times.
30 start_code_loc(stmt, token());
1194 30 next_token();
1195
1196 30 parse_alias(stmt, stmt->names, depth + 1);
1197
1198
4/5
✓ Branch 1 taken 21 times.
✓ Branch 4 taken 21 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
21 end_code_loc(stmt, token());
1199 21 add_inline_comment(stmt, depth);
1200 expect_tokens({tok_newline, tok_eof}, true, stmt, LOC);
1201 21 return stmt;
1202 }
1203
1204 StmtNode* Parser::parse_import_from(Node* parent, int depth) {
1205 TRACE_START();
1206
1207
1/1
✓ Branch 1 taken 44 times.
44 auto stmt = parent->new_object<ImportFrom>();
1208
4/5
✓ Branch 1 taken 44 times.
✓ Branch 4 taken 44 times.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 44 times.
44 start_code_loc(stmt, token());
1209
1/1
✓ Branch 1 taken 44 times.
44 next_token();
1210
1211 44 int level = 0;
1212
3/3
✓ Branch 1 taken 43 times.
✓ Branch 4 taken 43 times.
✓ Branch 7 taken 43 times.
44 stmt->module = parse_module_path(parent, level, depth);
1213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (level > 0) {
1214 stmt->level = level;
1215 }
1216
1217 expect_token(tok_import, true, stmt, LOC);
1218
1/1
✓ Branch 1 taken 24 times.
38 parse_alias(stmt, stmt->names, depth + 1);
1219
1220
4/5
✓ Branch 1 taken 24 times.
✓ Branch 4 taken 24 times.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 24 times.
24 end_code_loc(stmt, token());
1221
1/1
✓ Branch 1 taken 24 times.
24 add_inline_comment(stmt, depth);
1222 expect_tokens({tok_newline, tok_eof}, true, stmt, LOC);
1223 24 return stmt;
1224 }
1225
1226 StmtNode* Parser::parse_global(Node* parent, int depth) {
1227 TRACE_START();
1228
1229 6 auto stmt = parent->new_object<Global>();
1230
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 start_code_loc(stmt, token());
1231 6 next_token();
1232
1233
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 while (token().type() != tok_newline) {
1234
3/3
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 7 taken 6 times.
6 stmt->names.push_back(get_identifier());
1235 expect_token(tok_identifier, true, parent, LOC);
1236
1237
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (token().type() == ',') {
1238 next_token();
1239 } else {
1240 5 break;
1241 }
1242 }
1243
1244
4/5
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
5 end_code_loc(stmt, token());
1245 5 return stmt;
1246 }
1247
1248 StmtNode* Parser::parse_nonlocal(Node* parent, int depth) {
1249 TRACE_START();
1250
1251 6 auto stmt = parent->new_object<Nonlocal>();
1252
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 start_code_loc(stmt, token());
1253 6 next_token();
1254
1255
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 while (token().type() != tok_newline) {
1256
3/3
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 7 taken 6 times.
6 stmt->names.push_back(get_identifier());
1257 expect_token(tok_identifier, true, parent, LOC);
1258
1259
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (token().type() == ',') {
1260 next_token();
1261 } else {
1262 5 break;
1263 }
1264 }
1265
1266
4/5
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
5 end_code_loc(stmt, token());
1267 5 return stmt;
1268 }
1269
1270 StmtNode* Parser::parse_return(Node* parent, int depth) {
1271 TRACE_START();
1272
1273 286 auto stmt = parent->new_object<Return>();
1274
4/5
✓ Branch 1 taken 286 times.
✓ Branch 4 taken 286 times.
✓ Branch 6 taken 286 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 286 times.
286 start_code_loc(stmt, token());
1275 286 next_token();
1276
1277
2/2
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 9 times.
286 if (!is_tok_statement_ender()) {
1278
2/2
✓ Branch 1 taken 268 times.
✓ Branch 4 taken 268 times.
277 stmt->value = parse_expression(stmt, depth + 1, true);
1279
4/5
✓ Branch 1 taken 268 times.
✓ Branch 4 taken 268 times.
✓ Branch 6 taken 268 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 268 times.
268 end_code_loc(stmt, token());
1280 } else {
1281
4/5
✓ Branch 1 taken 9 times.
✓ Branch 4 taken 9 times.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 9 times.
9 end_code_loc(stmt, token());
1282
1283
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 if (token().type() != tok_comment) {
1284 9 next_token();
1285 }
1286 }
1287
1288 TRACE_END();
1289 277 return stmt;
1290 }
1291
1292 StmtNode* Parser::parse_del(Node* parent, int depth) {
1293 TRACE_START();
1294
1295 9 auto stmt = parent->new_object<Delete>();
1296
4/5
✓ Branch 1 taken 9 times.
✓ Branch 4 taken 9 times.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 9 times.
9 start_code_loc(stmt, token());
1297
1298
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 7 times.
23 while (!is_tok_statement_ender()) {
1299
1/1
✓ Branch 1 taken 16 times.
16 next_token();
1300
1301
1/1
✓ Branch 1 taken 14 times.
16 auto expr = parse_expression(stmt, depth + 1);
1302
1/1
✓ Branch 1 taken 14 times.
14 stmt->targets.push_back(expr);
1303
1304
3/3
✓ Branch 1 taken 14 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 7 times.
14 if (token().type() == ',') {
1305 7 continue;
1306 }
1307 }
1308
1309
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 end_code_loc(stmt, token());
1310 7 return stmt;
1311 }
1312
1313 StmtNode* Parser::parse_pass(Node* parent, int depth) {
1314 TRACE_START();
1315
1316 301 auto stmt = parent->new_object<Pass>();
1317
4/5
✓ Branch 1 taken 301 times.
✓ Branch 4 taken 301 times.
✓ Branch 6 taken 301 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 301 times.
301 start_code_loc(stmt, token());
1318
4/5
✓ Branch 1 taken 301 times.
✓ Branch 4 taken 301 times.
✓ Branch 6 taken 301 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 301 times.
301 end_code_loc(stmt, token());
1319 301 next_token();
1320 301 return stmt;
1321 }
1322
1323 StmtNode* Parser::parse_break(Node* parent, int depth) {
1324 TRACE_START();
1325
1326 #if AVOID_DUPLICATE_CONST
1327 static Break b;
1328 return &b;
1329 #endif
1330
1331 6 auto stmt = parent->new_object<Break>();
1332
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 start_code_loc(stmt, token());
1333
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 end_code_loc(stmt, token());
1334 6 next_token();
1335 6 return stmt;
1336 }
1337
1338 StmtNode* Parser::parse_continue(Node* parent, int depth) {
1339 TRACE_START();
1340
1341 #if AVOID_DUPLICATE_CONST
1342 static Continue c;
1343 return &c;
1344 #endif
1345
1346 7 auto stmt = parent->new_object<Continue>();
1347
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 start_code_loc(stmt, token());
1348
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 end_code_loc(stmt, token());
1349 7 next_token();
1350 7 return stmt;
1351 }
1352
1353 // Statement_2
1354 StmtNode* Parser::parse_assign(Node* parent, ExprNode* expr, int depth) {
1355 TRACE_START();
1356
1357 342 auto stmt = parent->new_object<Assign>();
1358 342 set_context(expr, ExprContext::Store);
1359 342 stmt->targets.push_back(expr);
1360
1361 // FIXME: this is the location of '=' not the start of the full expression
1362
4/5
✓ Branch 1 taken 342 times.
✓ Branch 4 taken 342 times.
✓ Branch 6 taken 342 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 342 times.
342 start_code_loc(stmt, token());
1363 342 next_token();
1364
1365 342 stmt->value = parse_expression(stmt, depth + 1, true);
1366
4/5
✓ Branch 1 taken 254 times.
✓ Branch 4 taken 254 times.
✓ Branch 6 taken 254 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 254 times.
254 end_code_loc(stmt, token());
1367 254 return stmt;
1368 }
1369
1370 StmtNode* Parser::parse_augassign(Node* parent, ExprNode* expr, int depth) {
1371 TRACE_START();
1372
1373
1/1
✓ Branch 1 taken 26 times.
26 auto stmt = parent->new_object<AugAssign>();
1374
1375 // this is a load-store
1376 // set_context(expr, ExprContext::Load);
1377 26 stmt->target = expr;
1378
1379 // FIXME: this is the location of the operator not the start of the full expression
1380
4/5
✓ Branch 1 taken 26 times.
✓ Branch 4 taken 26 times.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 26 times.
26 start_code_loc(stmt, token());
1381
1382
2/2
✓ Branch 1 taken 26 times.
✓ Branch 4 taken 26 times.
26 auto conf = get_operator_config(token());
1383 26 stmt->op = conf.binarykind;
1384
1/1
✓ Branch 1 taken 26 times.
26 next_token();
1385
1386
1/1
✓ Branch 1 taken 24 times.
26 stmt->value = parse_expression(stmt, depth + 1);
1387
4/5
✓ Branch 1 taken 24 times.
✓ Branch 4 taken 24 times.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 24 times.
24 end_code_loc(stmt, token());
1388 24 return stmt;
1389 }
1390
1391 StmtNode* Parser::parse_annassign(Node* parent, ExprNode* expr, int depth) {
1392 TRACE_START();
1393
1394 115 auto stmt = parent->new_object<AnnAssign>();
1395 115 set_context(expr, ExprContext::Store);
1396 115 stmt->target = expr;
1397
1398 // FIXME: this is the location of :' not the start of the full expression
1399
4/5
✓ Branch 1 taken 115 times.
✓ Branch 4 taken 115 times.
✓ Branch 6 taken 115 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 115 times.
115 start_code_loc(stmt, token());
1400 115 next_token();
1401
1402 115 stmt->annotation = parse_expression(stmt, depth + 1);
1403
1404
2/2
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 6 times.
109 if (token().type() == tok_assign) {
1405 expect_token(tok_assign, true, stmt, LOC);
1406
2/2
✓ Branch 1 taken 96 times.
✓ Branch 4 taken 96 times.
103 stmt->value = parse_expression(stmt, depth + 1);
1407 }
1408
1409
4/5
✓ Branch 1 taken 102 times.
✓ Branch 4 taken 102 times.
✓ Branch 6 taken 102 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 102 times.
102 end_code_loc(stmt, token());
1410 102 return stmt;
1411 }
1412
1413 // parse_expression_1
1414 ExprNode* Parser::parse_name(Node* parent, int depth) {
1415 TRACE_START();
1416
1417 3580 auto expr = parent->new_object<Name>();
1418
4/5
✓ Branch 1 taken 3580 times.
✓ Branch 4 taken 3580 times.
✓ Branch 6 taken 3580 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3580 times.
3580 start_code_loc(expr, token());
1419
1420
2/2
✓ Branch 1 taken 3580 times.
✓ Branch 4 taken 3580 times.
3580 expr->id = get_identifier();
1421 3580 expr->ctx = context();
1422
1423
4/5
✓ Branch 1 taken 3580 times.
✓ Branch 4 taken 3580 times.
✓ Branch 6 taken 3580 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3580 times.
3580 end_code_loc(expr, token());
1424 expect_token(tok_identifier, true, expr, LOC);
1425 3580 return expr;
1426 }
1427
1428 #define LY_UINT64_MAX sizeof("18446744073709551615") / sizeof(char)
1429 #define LY_UINT32_MAX sizeof("4294967295") / sizeof(char)
1430 #define LY_UINT16_MAX sizeof("65535") / sizeof(char)
1431 #define LY_UINT8_MAX sizeof("255") / sizeof(char)
1432
1433 // +1 char for the minus
1434 #define LY_INT64_MAX sizeof("9223372036854775807") / sizeof(char)
1435 #define LY_INT32_MAX sizeof("2147483647") / sizeof(char)
1436 #define LY_INT16_MAX sizeof("32767") / sizeof(char)
1437 #define LY_INT8_MAX sizeof("255") / sizeof(char)
1438
1439 bool Parser::is_valid_value() {
1440 780 String const& value = token().identifier();
1441
2/4
✓ Branch 1 taken 780 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 780 times.
780 int has_sign = value[0] == '-' || value[0] == '+';
1442
1443
4/5
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 541 times.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 57 times.
✗ Branch 6 not taken.
780 switch (token().type()) {
1444 74 case tok_string: {
1445 74 return true;
1446 }
1447 541 case tok_int: {
1448
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 541 times.
541 if (value.size() > 18 + has_sign) {
1449 return false;
1450 }
1451 541 return true;
1452 }
1453 108 case tok_float: {
1454 // Max numbers of digits
1455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 if (value.size() > 16 + has_sign) {
1456 return false;
1457 }
1458 108 return true;
1459 }
1460 57 case tok_none:
1461 case tok_true:
1462 57 case tok_false: return true;
1463 }
1464
1465 return false;
1466 }
1467
1468 ConstantValue Parser::get_value(Node* parent) {
1469
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 780 times.
780 if (!is_valid_value()) {
1470 ParsingError& error = parser_kwerror( //
1471 LOC, //
1472 "SyntaxError", //
1473 "Value is out of range" //
1474 );
1475 add_wip_expr(error, parent);
1476 PARSER_THROW(SyntaxError, error);
1477 }
1478
1479
6/7
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 541 times.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 41 times.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
780 switch (token().type()) {
1480
1481 74 case tok_string: {
1482
3/3
✓ Branch 1 taken 74 times.
✓ Branch 5 taken 74 times.
✓ Branch 8 taken 74 times.
74 return ConstantValue(token().identifier());
1483 }
1484 541 case tok_int: {
1485 // FIXME handle different sizes
1486 541 return ConstantValue(int32(token().as_integer()));
1487 }
1488 108 case tok_float: {
1489 108 return ConstantValue(token().as_float());
1490 }
1491 6 case tok_none: return ConstantValue(ConstantValue::none_t());
1492
1493 41 case tok_true: return ConstantValue(true);
1494
1495 10 case tok_false: return ConstantValue(false);
1496 }
1497
1498 return ConstantValue();
1499 }
1500
1501 ExprNode* Parser::parse_constant(Node* parent, int depth) {
1502 TRACE_START();
1503
1504 #if AVOID_DUPLICATE_CONST
1505 // Shortcut
1506 static Constant none = Constant(ConstantValue::none_t());
1507 static Constant truev = Constant(true);
1508 static Constant falsev = Constant(false);
1509
1510 switch (token().type()) {
1511 case tok_none: return none;
1512
1513 case tok_true: return truev;
1514
1515 case tok_false: return falsev;
1516 }
1517 //
1518 #endif
1519 644 auto expr = parent->new_object<Constant>();
1520
4/5
✓ Branch 1 taken 644 times.
✓ Branch 4 taken 644 times.
✓ Branch 6 taken 644 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 644 times.
644 start_code_loc(expr, token());
1521
1522
2/2
✓ Branch 1 taken 644 times.
✓ Branch 4 taken 644 times.
644 expr->value = get_value(expr);
1523
1524
4/5
✓ Branch 1 taken 644 times.
✓ Branch 4 taken 644 times.
✓ Branch 6 taken 644 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 644 times.
644 end_code_loc(expr, token());
1525 644 next_token();
1526 644 return expr;
1527 }
1528
1529 ExprNode* Parser::parse_await(Node* parent, int depth) {
1530 TRACE_START();
1531
1532 7 auto expr = parent->new_object<Await>();
1533
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 start_code_loc(expr, token());
1534 7 next_token();
1535
1536 7 expr->value = parse_expression(expr, depth + 1);
1537
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 end_code_loc(expr, token());
1538 6 return expr;
1539 }
1540
1541 ExprNode* Parser::parse_yield(Node* parent, int depth) {
1542 TRACE_START();
1543
1544
2/2
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 23 times.
30 if (peek_token().type() == tok_from) {
1545 7 return parse_yield_from(parent, depth);
1546 }
1547
1548 23 auto expr = parent->new_object<Yield>();
1549
4/5
✓ Branch 1 taken 23 times.
✓ Branch 4 taken 23 times.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 23 times.
23 start_code_loc(expr, token());
1550 23 next_token();
1551
1552
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 9 times.
23 if (!is_tok_statement_ender()) {
1553
2/2
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
14 expr->value = parse_expression(expr, depth + 1, true);
1554
4/5
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 13 times.
13 end_code_loc(expr, token());
1555 } else {
1556
4/5
✓ Branch 1 taken 9 times.
✓ Branch 4 taken 9 times.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 9 times.
9 end_code_loc(expr, token());
1557
1558
2/2
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1 times.
9 if (token().type() != tok_comment) {
1559 8 next_token();
1560 }
1561 }
1562
1563 22 return expr;
1564 }
1565
1566 ExprNode* Parser::parse_yield_from(Node* parent, int depth) {
1567 TRACE_START();
1568
1569 7 auto expr = parent->new_object<YieldFrom>();
1570
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 start_code_loc(expr, token());
1571 7 next_token(); // eat yield
1572
1573 expect_token(tok_from, true, expr, LOC);
1574 7 expr->value = parse_expression(expr, depth + 1);
1575
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 end_code_loc(expr, token());
1576 6 return expr;
1577 }
1578
1579 bool is_star(Token const& tok) { return tok.type() == tok_operator && tok.operator_name() == "*"; }
1580
1581 bool is_starstar(Token const& tok) {
1582
3/4
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 288 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
305 return tok.type() == tok_operator && tok.operator_name() == "**";
1583 }
1584
1585 Arguments Parser::parse_arguments(Node* parent, char kind, int depth) {
1586 TRACE_START();
1587
1588 219 Arguments args;
1589 //
1590
1591 219 bool keywords = false;
1592
1593
3/3
✓ Branch 1 taken 494 times.
✓ Branch 4 taken 305 times.
✓ Branch 5 taken 189 times.
494 while (token().type() != kind) {
1594 305 ExprNode* value = nullptr;
1595
1596
1/1
✓ Branch 1 taken 305 times.
305 Arg arg;
1597
1598 305 bool vararg = false;
1599 305 bool kwarg = false;
1600
1601
3/3
✓ Branch 1 taken 305 times.
✓ Branch 4 taken 139 times.
✓ Branch 5 taken 166 times.
305 if (token().type() == tok_comma) {
1602
1/1
✓ Branch 1 taken 139 times.
139 next_token();
1603 }
1604
1605
4/4
✓ Branch 1 taken 305 times.
✓ Branch 4 taken 305 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 281 times.
305 if (is_star(token())) {
1606
1/1
✓ Branch 1 taken 24 times.
24 next_token();
1607 24 vararg = true;
1608 }
1609
1610
4/4
✓ Branch 1 taken 305 times.
✓ Branch 4 taken 305 times.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 288 times.
305 if (is_starstar(token())) {
1611
1/1
✓ Branch 1 taken 17 times.
17 next_token();
1612 17 kwarg = true;
1613 }
1614
1615
3/3
✓ Branch 1 taken 305 times.
✓ Branch 4 taken 305 times.
✓ Branch 7 taken 305 times.
305 start_code_loc(&arg, token());
1616
2/2
✓ Branch 1 taken 305 times.
✓ Branch 4 taken 305 times.
305 arg.arg = get_identifier();
1617 expect_token(tok_identifier, true, parent, LOC);
1618
1619
7/7
✓ Branch 1 taken 280 times.
✓ Branch 4 taken 126 times.
✓ Branch 5 taken 154 times.
✓ Branch 6 taken 119 times.
✓ Branch 7 taken 7 times.
✓ Branch 8 taken 119 times.
✓ Branch 9 taken 161 times.
280 if (token().type() == ':' && kind != ':') {
1620
1/1
✓ Branch 1 taken 119 times.
119 next_token();
1621
2/2
✓ Branch 1 taken 117 times.
✓ Branch 4 taken 117 times.
119 arg.annotation = parse_expression(parent, depth + 1);
1622 }
1623
1624
3/3
✓ Branch 1 taken 278 times.
✓ Branch 4 taken 62 times.
✓ Branch 5 taken 216 times.
278 if (token().type() == tok_assign) {
1625
1/1
✓ Branch 1 taken 62 times.
62 next_token();
1626
1/1
✓ Branch 1 taken 59 times.
62 value = parse_expression(parent, depth + 1);
1627 }
1628
1629
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 252 times.
275 if (vararg) {
1630
1/1
✓ Branch 1 taken 23 times.
23 args.vararg = arg;
1631 // only kwargs from that point onward
1632 23 keywords = true;
1633
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 236 times.
252 } else if (kwarg) {
1634
1/1
✓ Branch 1 taken 16 times.
16 args.kwarg = arg;
1635
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 20 times.
236 } else if (!keywords) {
1636
1/1
✓ Branch 1 taken 216 times.
216 args.args.push_back(arg);
1637
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 176 times.
216 if (value) {
1638
1/1
✓ Branch 1 taken 40 times.
40 args.defaults.push_back(value);
1639 }
1640
3/3
✓ Branch 1 taken 216 times.
✓ Branch 4 taken 216 times.
✓ Branch 7 taken 216 times.
216 end_code_loc(&arg, token());
1641 } else {
1642
1/1
✓ Branch 1 taken 20 times.
20 args.kwonlyargs.push_back(arg);
1643 // NB: value can be null here
1644
1/1
✓ Branch 1 taken 20 times.
20 args.kw_defaults.push_back(value);
1645 }
1646 305 }
1647
1648 //
1649 expect_token(kind, true, parent, LOC);
1650 189 return args;
1651 30 }
1652
1653 ExprNode* Parser::parse_lambda(Node* parent, int depth) {
1654 TRACE_START();
1655
1656 9 auto expr = parent->new_object<Lambda>();
1657
4/5
✓ Branch 1 taken 9 times.
✓ Branch 4 taken 9 times.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 9 times.
9 start_code_loc(expr, token());
1658 9 next_token();
1659
1660
2/2
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
9 expr->args = parse_arguments(expr, ':', depth + 1);
1661 7 expr->body = parse_expression(expr, depth + 1);
1662
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 end_code_loc(expr, token());
1663 6 return expr;
1664 }
1665
1666 ExprNode* Parser::parse_starred(Node* parent, int depth) {
1667 TRACE_START();
1668
1669 8 auto expr = parent->new_object<Starred>();
1670 8 next_token();
1671
1672 8 expr->value = parse_expression(expr, depth + 1);
1673 7 return expr;
1674 }
1675
1676 void Parser::parse_comprehension(Node* parent, Array<Comprehension>& out, char kind, int depth) {
1677 TRACE_START();
1678
1679
1/1
✓ Branch 1 taken 56 times.
56 PopGuard _(parsing_context, ParsingContext::Comprehension);
1680
1681
3/3
✓ Branch 1 taken 92 times.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 24 times.
92 while (token().type() != kind) {
1682 expect_token(tok_for, true, parent, LOC);
1683 56 Comprehension cmp;
1684
1685
1/1
✓ Branch 1 taken 52 times.
56 cmp.target = parse_star_targets(parent, depth + 1);
1686
1/1
✓ Branch 1 taken 52 times.
52 set_context(cmp.target, ExprContext::Store);
1687
1688 expect_token(tok_in, true, parent, LOC);
1689
1/1
✓ Branch 1 taken 44 times.
48 cmp.iter = parse_expression(parent, depth + 1);
1690
1691
3/3
✓ Branch 1 taken 76 times.
✓ Branch 4 taken 40 times.
✓ Branch 5 taken 36 times.
76 while (token().type() == tok_if) {
1692
1/1
✓ Branch 1 taken 40 times.
40 next_token();
1693
2/2
✓ Branch 1 taken 32 times.
✓ Branch 4 taken 32 times.
40 cmp.ifs.push_back(parse_expression(parent, depth + 1));
1694 }
1695
1696
1/1
✓ Branch 1 taken 36 times.
36 cmp.is_async = async();
1697
1/1
✓ Branch 1 taken 36 times.
36 out.push_back(cmp);
1698 56 }
1699 56 }
1700
1701 template <typename Comp>
1702 ExprNode* parse_comprehension(Parser* parser, Node* parent, ExprNode* child, char kind, int depth) {
1703 84 auto expr = parent->new_object<Comp>();
1704
1705 84 expr->elt = child;
1706 84 parser->parse_comprehension(expr, expr->generators, kind, depth);
1707
4/5
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
36 parser->end_code_loc(expr, parser->token());
1708
1709
2/2
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
54 parser->expect_token(kind, true, parent, LOC);
1710 36 return expr;
1711 }
1712
1713 ExprNode* parse_dictcomprehension(
1714 Parser* parser, Node* parent, ExprNode* key, ExprNode* value, char kind, int depth) {
1715 14 auto expr = parent->new_object<DictComp>();
1716
1717 14 expr->key = key;
1718 14 expr->value = value;
1719 14 parser->parse_comprehension(expr, expr->generators, kind, depth);
1720
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 parser->end_code_loc(expr, parser->token());
1721
1722 parser->expect_token(kind, true, parent, LOC);
1723 6 return expr;
1724 }
1725
1726 template <typename Literal>
1727 ExprNode* parse_literal(Parser* parser, Node* parent, ExprNode* child, char kind, int depth) {
1728
6/7
✓ Branch 3 taken 169 times.
✓ Branch 7 taken 169 times.
✓ Branch 11 taken 169 times.
✓ Branch 14 taken 169 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 169 times.
✓ Branch 20 taken 169 times.
845 TRACE_START2(parser->token());
1729
1730 // This is a tuple
1731 338 auto expr = parent->new_object<Literal>();
1732
1733
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
338 if (child) {
1734 338 expr->elts.push_back(child);
1735 }
1736 // {a, b, c}
1737 // [a, b, c]
1738 // (a, b, c)
1739 104 while (true) {
1740
2/2
✓ Branch 1 taken 193 times.
✓ Branch 4 taken 193 times.
442 expr->elts.push_back(parser->parse_expression(parent, depth + 1));
1741
1742
2/2
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 141 times.
386 if (parser->token().type() == ',') {
1743 104 parser->next_token();
1744 } else {
1745
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 65 times.
282 if (kind) {
1746
2/2
✓ Branch 1 taken 76 times.
✓ Branch 4 taken 65 times.
228 parser->expect_token(kind, true, expr, LOC);
1747 }
1748 260 break;
1749 }
1750 }
1751
1752
4/5
✓ Branch 1 taken 130 times.
✓ Branch 4 taken 130 times.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 130 times.
260 parser->end_code_loc(expr, parser->token());
1753
6/7
✓ Branch 1 taken 130 times.
✓ Branch 5 taken 130 times.
✓ Branch 9 taken 130 times.
✓ Branch 12 taken 130 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 130 times.
✓ Branch 18 taken 130 times.
650 TRACE_END2(parser->token());
1754 260 return expr;
1755 }
1756
1757 ExprNode* parse_dictliteral(
1758 Parser* parser, Node* parent, ExprNode* key, ExprNode* value, char kind, int depth) {
1759 // This is a tuple
1760 37 auto expr = parent->new_object<DictExpr>();
1761 37 expr->keys.push_back(key);
1762 37 expr->values.push_back(value);
1763
1764 // {a: b, c: d}
1765
1/2
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
37 while (parser->token().type() != kind) {
1766
2/2
✓ Branch 1 taken 33 times.
✓ Branch 4 taken 33 times.
37 expr->keys.push_back(parser->parse_expression(parent, depth + 1));
1767 parser->expect_token(':', true, expr, LOC);
1768
1769
2/2
✓ Branch 1 taken 25 times.
✓ Branch 4 taken 25 times.
29 expr->values.push_back(parser->parse_expression(parent, depth + 1));
1770
1771
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
25 if (parser->token().type() == ',') {
1772 parser->next_token();
1773 } else {
1774 parser->expect_token(kind, true, expr, LOC);
1775 21 break;
1776 }
1777 }
1778
1779
4/5
✓ Branch 1 taken 21 times.
✓ Branch 4 taken 21 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
21 parser->end_code_loc(expr, parser->token());
1780 21 return expr;
1781 }
1782
1783 template <typename Comp, typename Literal>
1784 ExprNode*
1785 parse_comprehension_or_literal(Parser* parser, Node* parent, int tok, char kind, int depth) {
1786 // Save the start token to set the code loc when we know if this is a tuple or a generator
1787
2/2
✓ Branch 1 taken 233 times.
✓ Branch 4 taken 233 times.
466 auto start_tok = parser->token();
1788
3/3
✓ Branch 1 taken 233 times.
✓ Branch 4 taken 233 times.
✓ Branch 7 taken 233 times.
1165 SHOW_TOK(start_tok);
1789
2/2
✓ Branch 1 taken 233 times.
✓ Branch 4 taken 233 times.
699 parser->expect_token(tok, true, nullptr, LOC); // eat ( [ {
1790
1791 // Warning: the parent is wrong but we need to parse the expression right now
1792
1/1
✓ Branch 1 taken 214 times.
466 auto child = parser->parse_expression(parent, depth + 1);
1793 428 ExprNode* value = nullptr;
1794 428 bool dictionary = false;
1795
1796 // Dictionary
1797
3/3
✓ Branch 1 taken 214 times.
✓ Branch 4 taken 61 times.
✓ Branch 5 taken 153 times.
428 if (parser->token().type() == ':') {
1798
1/1
✓ Branch 1 taken 61 times.
122 parser->next_token();
1799
1/1
✓ Branch 1 taken 56 times.
122 value = parser->parse_expression(parent, depth + 1);
1800 112 dictionary = true;
1801 }
1802 // ----
1803
1804 //
1805 418 ExprNode* expr = nullptr;
1806
3/3
✓ Branch 1 taken 209 times.
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 153 times.
418 if (parser->token().type() == tok_for) {
1807 // This is generator comprehension
1808
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 42 times.
112 if (dictionary) {
1809
1/1
✓ Branch 1 taken 6 times.
28 expr = parse_dictcomprehension(parser, parent, child, value, kind, depth);
1810 } else {
1811
1/1
✓ Branch 1 taken 18 times.
84 expr = parse_comprehension<Comp>(parser, parent, child, kind, depth);
1812
3/3
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 7 taken 18 times.
90 kwerror("Done {}", str(expr));
1813 }
1814
3/3
✓ Branch 1 taken 153 times.
✓ Branch 4 taken 124 times.
✓ Branch 5 taken 29 times.
306 } else if (parser->token().type() == ',') {
1815
1/1
✓ Branch 1 taken 124 times.
248 parser->next_token();
1816
1817
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 87 times.
248 if (dictionary) {
1818
1/1
✓ Branch 1 taken 21 times.
74 expr = parse_dictliteral(parser, parent, child, value, kind, depth);
1819 } else {
1820
1/1
✓ Branch 1 taken 65 times.
174 expr = parse_literal<Literal>(parser, parent, child, kind, depth);
1821 }
1822 } else {
1823 // This is not a literal nor a list-comprehension
1824 // (2 + 1)
1825
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
58 if (kind == ')' && !dictionary) {
1826
1/1
✓ Branch 1 taken 9 times.
18 auto p = parser->parse_expression_1(parent, child, 0, depth);
1827
2/2
✓ Branch 1 taken 9 times.
✓ Branch 4 taken 6 times.
27 parser->expect_token(')', true, parent, LOC);
1828 12 return p;
1829 }
1830
1831
2/2
✓ Branch 1 taken 20 times.
✓ Branch 4 taken 20 times.
60 kwerror("Unhandled list-comprehension case");
1832 }
1833
1834
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 110 times.
260 if (expr == nullptr) {
1835
2/2
✓ Branch 2 taken 20 times.
✓ Branch 6 taken 20 times.
80 ParsingError& error = parser->parser_kwerror( //
1836
2/2
✓ Branch 1 taken 20 times.
✓ Branch 4 taken 20 times.
60 LOC, //
1837 "SyntaxError", //
1838 "Comprehension is null" //
1839 );
1840
1/1
✓ Branch 1 taken 20 times.
40 add_wip_expr(error, parent);
1841
1/1
✓ Branch 2 taken 20 times.
40 PARSER_THROW(SyntaxError, error);
1842 }
1843
1844 // fix the things we could not do at the begining
1845
4/5
✓ Branch 1 taken 110 times.
✓ Branch 4 taken 110 times.
✓ Branch 6 taken 110 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 110 times.
220 parser->end_code_loc(expr, parser->token());
1846
3/4
✓ Branch 1 taken 110 times.
✓ Branch 3 taken 110 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 110 times.
220 parser->start_code_loc(expr, start_tok);
1847
1/1
✓ Branch 1 taken 110 times.
220 child->move(expr);
1848 // ----------------------------------------------
1849
1850
4/4
✓ Branch 1 taken 110 times.
✓ Branch 4 taken 110 times.
✓ Branch 7 taken 110 times.
✓ Branch 10 taken 110 times.
550 SHOW_TOK(parser->token());
1851 220 return expr;
1852 466 }
1853
1854 // [a, b] or [a for b in c]
1855 ExprNode* Parser::parse_list(Node* parent, int depth) {
1856 TRACE_START();
1857 56 return parse_comprehension_or_literal<ListComp, ListExpr>(
1858 27 this, parent, tok_square, ']', depth + 1);
1859 }
1860
1861 // (a, b) or (a for b in c)
1862 ExprNode* Parser::parse_tuple_generator(Node* parent, int depth) {
1863 TRACE_START();
1864 53 return parse_comprehension_or_literal<GeneratorExp, TupleExpr>(
1865 35 this, parent, tok_parens, ')', depth + 1);
1866 }
1867
1868 // {a, b} or {a for b in c} or {a: b, c: d} or {a: b for a, b in c}
1869 ExprNode* Parser::parse_set_dict(Node* parent, int depth) {
1870 TRACE_START();
1871 124 return parse_comprehension_or_literal<SetComp, SetExpr>(this, parent, tok_curly, '}', depth);
1872 }
1873
1874 ExprNode* Parser::parse_ifexp(Node* parent, ExprNode* primary, int depth) {
1875
1876 // if is part of the comprehension
1877
4/4
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 10 times.
90 if (parsing_context.size() > 0 &&
1878
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 parsing_context[parsing_context.size() - 1] == ParsingContext::Comprehension) {
1879 40 return primary;
1880 }
1881
1882 // body if test else body
1883 10 IfExp* expr = parent->new_object<IfExp>();
1884
4/5
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 10 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10 times.
10 start_code_loc(expr, token());
1885 10 next_token();
1886
1887 10 primary->move(expr);
1888 10 expr->body = primary;
1889
1890 10 expr->test = parse_expression(expr, depth + 1);
1891
1892 expect_token(tok_else, true, expr, LOC);
1893 8 expr->orelse = parse_expression(expr, depth + 1);
1894
1895
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 end_code_loc(expr, token());
1896 7 return expr;
1897 }
1898
1899 // parse_expression_2
1900 ExprNode* Parser::parse_named_expr(Node* parent, ExprNode* primary, int depth) {
1901 TRACE_START();
1902
1903 7 auto expr = parent->new_object<NamedExpr>();
1904 7 expr->target = primary;
1905
1906 // FIXME: this is the location of ':=' not the start of the full expression
1907
4/5
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
7 start_code_loc(expr, token());
1908 7 next_token();
1909
1910 7 expr->value = parse_expression(parent, depth + 1);
1911
1912
4/5
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
6 end_code_loc(expr, token());
1913 6 return expr;
1914 }
1915
1916 ExprNode* Parser::parse_bool_operator(Node* parent, ExprNode* primary, int depth) {
1917 TRACE_START();
1918 return not_implemented_expr(parent);
1919 }
1920 ExprNode* Parser::parse_binary_operator(Node* parent, ExprNode* primary, int depth) {
1921 TRACE_START();
1922 return not_implemented_expr(parent);
1923 }
1924 ExprNode* Parser::parse_compare_operator(Node* parent, ExprNode* primary, int depth) {
1925 TRACE_START();
1926 return not_implemented_expr(parent);
1927 }
1928 ExprNode* Parser::parse_suffix_unary(Node* parent, ExprNode* primary, int depth) {
1929 TRACE_START();
1930 return not_implemented_expr(parent);
1931 }
1932
1933 ExprNode* Parser::parse_prefix_unary(Node* parent, int depth) {
1934 TRACE_START();
1935
1/1
✓ Branch 1 taken 39 times.
39 auto expr = parent->new_object<UnaryOp>();
1936
4/5
✓ Branch 1 taken 39 times.
✓ Branch 4 taken 39 times.
✓ Branch 6 taken 39 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 39 times.
39 start_code_loc(expr, token());
1937
1938
2/2
✓ Branch 1 taken 39 times.
✓ Branch 4 taken 39 times.
39 auto conf = get_operator_config(token());
1939
1940
3/3
✓ Branch 1 taken 39 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 31 times.
39 if (token().operator_name() == "*") {
1941
1/1
✓ Branch 1 taken 7 times.
8 return parse_starred(parent, depth);
1942 }
1943
1944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (conf.unarykind == UnaryOperator::None) {
1945 ParsingError& error = parser_kwerror( //
1946 LOC, //
1947 "SyntaxError", //
1948 fmtstr("Expected an unary operator not {}", //
1949 str(token())));
1950
1951 add_wip_expr(error, parent);
1952 PARSER_THROW(SyntaxError, error);
1953 }
1954
1955
1/1
✓ Branch 1 taken 31 times.
31 next_token();
1956
1957 31 expr->op = conf.unarykind;
1958
1/1
✓ Branch 1 taken 27 times.
31 expr->operand = parse_expression(expr, depth + 1);
1959
1960
4/5
✓ Branch 1 taken 27 times.
✓ Branch 4 taken 27 times.
✓ Branch 6 taken 27 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 27 times.
27 end_code_loc(expr, token());
1961 27 return expr;
1962 }
1963
1964 Token Parser::parse_call_args(Node* expr,
1965 Array<ExprNode*>& args,
1966 Array<Keyword>& keywords,
1967 int depth) {
1968 TRACE_START();
1969
1970 193 bool keyword = false;
1971
2/2
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 51 times.
360 while (token().type() != ')') {
1972
1973 // if not in keyword mode check if next argument is one
1974
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 1 times.
309 if (keyword == false) {
1975
2/2
✓ Branch 1 taken 308 times.
✓ Branch 4 taken 308 times.
308 auto lookahead = _lex.peek_token();
1976
7/7
✓ Branch 1 taken 308 times.
✓ Branch 4 taken 257 times.
✓ Branch 5 taken 51 times.
✓ Branch 7 taken 78 times.
✓ Branch 8 taken 179 times.
✓ Branch 9 taken 78 times.
✓ Branch 10 taken 230 times.
308 if (token().type() == tok_identifier && lookahead.type() == tok_assign) {
1977 78 keyword = true;
1978 }
1979 308 }
1980
1981
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 79 times.
309 if (!keyword) {
1982
1/1
✓ Branch 1 taken 219 times.
230 auto arg = parse_expression(expr, depth + 1);
1983
1/1
✓ Branch 1 taken 219 times.
219 args.push_back(arg);
1984 } else {
1985
1/1
✓ Branch 1 taken 79 times.
79 auto kwarg = Keyword();
1986
2/2
✓ Branch 1 taken 79 times.
✓ Branch 4 taken 79 times.
79 kwarg.arg = get_identifier(); // <= NB: this checks for tok_identifier
1987 // if not returns a dummy identifier
1988 expect_token(tok_identifier, true, expr, LOC);
1989 expect_token(tok_assign, true, expr, LOC);
1990
1991
1/1
✓ Branch 1 taken 75 times.
79 kwarg.value = parse_expression(expr, depth + 1);
1992
1/1
✓ Branch 1 taken 75 times.
75 keywords.push_back(kwarg);
1993 79 }
1994
1995
2/2
✓ Branch 2 taken 167 times.
✓ Branch 3 taken 127 times.
294 if (token().type() == ',') {
1996 167 next_token();
1997 } else {
1998 127 break;
1999 }
2000 }
2001
2002 178 auto last = token();
2003 expect_token(')', true, expr, LOC);
2004 163 return last;
2005 15 }
2006
2007 ExprNode* Parser::parse_call(Node* parent, ExprNode* primary, int depth) {
2008 TRACE_START();
2009
2010
1/1
✓ Branch 1 taken 175 times.
175 auto expr = parent->new_object<Call>();
2011
4/5
✓ Branch 1 taken 175 times.
✓ Branch 4 taken 175 times.
✓ Branch 6 taken 175 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 175 times.
175 start_code_loc(expr, token());
2012 175 expr->func = primary;
2013
2014 // FIXME: this is the location of '(' not the start of the full expression
2015
4/5
✓ Branch 1 taken 175 times.
✓ Branch 4 taken 175 times.
✓ Branch 6 taken 175 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 175 times.
175 start_code_loc(expr, token());
2016 expect_token(tok_parens, true, expr, LOC);
2017
2018
1/1
✓ Branch 1 taken 151 times.
175 auto last = parse_call_args(expr, expr->args, expr->keywords, depth + 1);
2019
3/4
✓ Branch 1 taken 151 times.
✓ Branch 3 taken 151 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 151 times.
151 end_code_loc(expr, last);
2020
2021 TRACE_END();
2022 151 return expr;
2023 151 }
2024
2025 ExprNode* Parser::parse_attribute(Node* parent, ExprNode* primary, int depth) {
2026 TRACE_START();
2027
2028 49 auto expr = parent->new_object<Attribute>();
2029 49 expr->value = primary;
2030
2031 // FIXME: this is the location of '.' not the start of the full expression
2032
4/5
✓ Branch 1 taken 49 times.
✓ Branch 4 taken 49 times.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 49 times.
49 start_code_loc(expr, token());
2033 49 next_token();
2034
2035
2/2
✓ Branch 1 taken 49 times.
✓ Branch 4 taken 49 times.
49 expr->attr = get_identifier();
2036
2037
4/5
✓ Branch 1 taken 49 times.
✓ Branch 4 taken 49 times.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 49 times.
49 end_code_loc(expr, token());
2038 expect_token(tok_identifier, true, expr, LOC);
2039
2040 // expr->ctx = ;
2041 45 return expr;
2042 }
2043
2044 ExprNode* Parser::parse_subscript(Node* parent, ExprNode* primary, int depth) {
2045 TRACE_START();
2046
2047
1/1
✓ Branch 1 taken 21 times.
21 auto expr = parent->new_object<Subscript>();
2048 21 expr->value = primary;
2049
2050 // FIXME: this is the location of '[' not the start of the full expression
2051
4/5
✓ Branch 1 taken 21 times.
✓ Branch 4 taken 21 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
21 start_code_loc(expr, token());
2052 expect_token(tok_square, true, expr, LOC);
2053
2054 // We do not allocate the TupleExpr unless required
2055 21 Array<ExprNode*> elts;
2056
2057 // a[2:3] => Slice(2, 3)
2058 // a[1:2, 2:3] => Tuple(Slice(1, 2), Slice(2, 3))
2059 // a[1:2, 2:3] => Tuple(Slice(1, 2), Slice(2, 3))
2060 // a[1, 2, 3] => Tuple(1, 2, 3)
2061 //
2062 {
2063
1/1
✓ Branch 1 taken 21 times.
21 PopGuard _(parsing_context, ParsingContext::Slice);
2064
2065
2/3
✓ Branch 1 taken 21 times.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
21 while (token().type() != ']') {
2066
2/2
✓ Branch 1 taken 17 times.
✓ Branch 4 taken 17 times.
21 elts.push_back(parse_expression(expr, depth + 1));
2067
2068
2/3
✓ Branch 1 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 if (token().type() == ',') {
2069 next_token();
2070 } else {
2071 expect_token(']', true, expr, LOC);
2072 13 break;
2073 }
2074 }
2075 21 }
2076
2077
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (elts.size() == 0) {
2078 ParsingError& error = parser_kwerror( //
2079 LOC, //
2080 "SyntaxError", //
2081 "Substript needs at least one argument" //
2082 );
2083 add_wip_expr(error, parent);
2084 PARSER_THROW(SyntaxError, error);
2085 }
2086
2087
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 if (elts.size() == 1) {
2088 13 expr->slice = elts[0];
2089 }
2090
2091
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (elts.size() > 1) {
2092 auto tuple = expr->new_object<TupleExpr>();
2093 tuple->elts = elts;
2094 expr->slice = tuple;
2095 }
2096
2097
4/5
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 13 times.
13 end_code_loc(expr, token());
2098 13 return expr;
2099 21 }
2100
2101 void Parser::error_recovery(ParsingError* error) {
2102
4/4
✓ Branch 1 taken 607 times.
✓ Branch 5 taken 607 times.
✓ Branch 7 taken 42 times.
✓ Branch 8 taken 565 times.
607 while (!in(token().type(), tok_newline, tok_eof)) {
2103 42 error->remaining.push_back(token());
2104 42 next_token();
2105 }
2106 565 error->line = currentline.tokens;
2107
2108
2/2
✓ Branch 1 taken 526 times.
✓ Branch 2 taken 39 times.
565 if (error->line.size() > 0) {
2109 526 Token const& start = error->line[0];
2110 526 Token const& end = error->line[int(error->line.size() - 1)];
2111
2112 // then we got a new line
2113
2/2
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 7 times.
526 if (!error->received_token.isbetween(start, end)) {
2114 519 error->received_token = end;
2115 }
2116 } else {
2117 kwerror("Was not able to retrieve the tok line for an error");
2118 }
2119 565 }
2120
2121 ExprNode* Parser::parse_slice(Node* parent, ExprNode* primary, int depth) {
2122 TRACE_START();
2123
2124
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (!allow_slice()) {
2125 ParsingError& error = parser_kwerror( //
2126 LOC, //
2127 "SyntaxError", //
2128 "Slice is not allowed in this context" //
2129 );
2130 add_wip_expr(error, primary);
2131 PARSER_THROW(SyntaxError, error);
2132
2133 // fallback to primary
2134 return primary;
2135 }
2136
2137 18 auto expr = parent->new_object<Slice>();
2138
4/5
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
18 start_code_loc(expr, token());
2139
2140 18 expr->lower = primary;
2141 expect_token(':', true, expr, LOC);
2142
2143
2/2
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
18 expr->upper = parse_expression(expr, depth + 1);
2144
2145
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (token().type() == ':') {
2146 next_token();
2147 expr->step = parse_expression(expr, depth + 1);
2148 }
2149 15 return expr;
2150 }
2151
2152 void set_decorators(StmtNode* stmt, Array<Decorator>& decorators) {
2153
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 1817 times.
1836 if (decorators.size() > 0) {
2154
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6 times.
19 if (stmt->kind == NodeKind::FunctionDef) {
2155 13 auto fun = cast<FunctionDef>(stmt);
2156 13 fun->decorator_list = decorators;
2157
2158
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (stmt->kind == NodeKind::ClassDef) {
2159 6 auto cls = cast<ClassDef>(stmt);
2160 6 cls->decorator_list = decorators;
2161 }
2162 }
2163 1836 }
2164
2165 StmtNode* Parser::parse_statement(Node* parent, int depth) {
2166
2167 TRACE_START();
2168
2169 2395 Array<Decorator> decorators;
2170
3/3
✓ Branch 1 taken 2530 times.
✓ Branch 4 taken 156 times.
✓ Branch 5 taken 2374 times.
2530 while (token().type() == tok_decorator) {
2171
1/1
✓ Branch 1 taken 156 times.
156 next_token();
2172
2173 156 Comment* comment = nullptr;
2174
1/1
✓ Branch 1 taken 135 times.
156 auto fun = parse_expression(parent, depth);
2175
2176
3/3
✓ Branch 1 taken 135 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 130 times.
135 if (token().type() == tok_comment) {
2177
1/1
✓ Branch 1 taken 5 times.
5 comment = parse_comment(fun, depth);
2178 }
2179
2180
1/1
✓ Branch 1 taken 135 times.
135 decorators.emplace_back(fun, comment);
2181
2182
3/3
✓ Branch 1 taken 135 times.
✓ Branch 4 taken 128 times.
✓ Branch 5 taken 7 times.
135 if (token().type() == tok_newline) {
2183
1/1
✓ Branch 1 taken 128 times.
128 next_token();
2184 }
2185 }
2186
2187
1/1
✓ Branch 1 taken 1836 times.
2374 auto stmt = parse_statement_primary(parent, depth + 1);
2188
1/1
✓ Branch 1 taken 1836 times.
1836 set_decorators(stmt, decorators);
2189
2190
3/3
✓ Branch 1 taken 1836 times.
✓ Branch 4 taken 1823 times.
✓ Branch 5 taken 13 times.
1836 if (token().type() != ';') {
2191 TRACE_END();
2192 1823 return stmt;
2193 }
2194
2195 13 Array<StmtNode*> body;
2196
1/1
✓ Branch 1 taken 13 times.
13 body.push_back(stmt);
2197
2198
3/3
✓ Branch 1 taken 30 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 9 times.
30 while (token().type() == ';') {
2199
1/1
✓ Branch 1 taken 21 times.
21 next_token();
2200
2201
3/3
✓ Branch 1 taken 21 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 19 times.
21 if (is_tok_statement_ender()) {
2202 2 break;
2203 }
2204
2205
1/1
✓ Branch 1 taken 17 times.
19 stmt = parse_statement_primary(parent, depth + 1);
2206
1/1
✓ Branch 1 taken 17 times.
17 body.push_back(stmt);
2207 }
2208
2209 11 stmt = nullptr;
2210
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
11 if (body.size() == 1) {
2211 1 stmt = body[0];
2212 } else {
2213
1/1
✓ Branch 1 taken 10 times.
10 auto inlinestmt = parent->new_object<Inline>();
2214
1/1
✓ Branch 1 taken 10 times.
10 inlinestmt->body = body;
2215 10 stmt = inlinestmt;
2216 }
2217
2218 TRACE_END();
2219 11 return stmt;
2220 2397 }
2221
2222 StmtNode* Parser::parse_yield_stmt(Node* parent, int depth) {
2223 // yield is an expression in the AST but it can be parsed
2224 // as simple_statement or an expression
2225 30 auto stmt = parent->new_object<Expr>();
2226 30 stmt->value = parse_yield(stmt, depth);
2227 28 return stmt;
2228 }
2229
2230 StmtNode* Parser::parse_comment_stmt(Node* parent, int depth) {
2231 116 Expr* comment_stmt = parent->new_object<Expr>();
2232 116 ExprNode* comment = parse_comment(comment_stmt, depth);
2233
2234 116 comment_stmt->value = comment;
2235
2236 expect_tokens({tok_newline, tok_eof}, true, comment_stmt, LOC);
2237 116 return comment_stmt;
2238 }
2239
2240 StmtNode* Parser::parse_statement_primary(Node* parent, int depth) {
2241 TRACE_START();
2242
2243
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2393 times.
2393 if (previous == token()) {
2244 ParsingError& error = parser_kwerror( //
2245 LOC, //
2246 "SyntaxError", //
2247 fmtstr("Unhandled token {} `{}` previous tok was `{}`", //
2248 token().type(), //
2249 str(token()), //
2250 str(previous) //
2251 ) //
2252 );
2253 add_wip_expr(error, parent);
2254 PARSER_THROW(SyntaxError, error);
2255 } else {
2256 2393 previous = token();
2257 }
2258
2259 // Statement we can guess rightaway from the current token we are seeing
2260
21/23
✗ Branch 2 not taken.
✓ Branch 3 taken 286 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 44 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 301 times.
✓ Branch 8 taken 9 times.
✓ Branch 9 taken 30 times.
✓ Branch 10 taken 20 times.
✓ Branch 11 taken 6 times.
✓ Branch 12 taken 7 times.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 6 times.
✓ Branch 15 taken 216 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 33 times.
✓ Branch 18 taken 76 times.
✓ Branch 19 taken 52 times.
✓ Branch 20 taken 48 times.
✓ Branch 21 taken 35 times.
✓ Branch 22 taken 25 times.
✓ Branch 23 taken 141 times.
✓ Branch 24 taken 1006 times.
2393 switch (token().type()) {
2261 // clang-format off
2262
2263 // Small Statement
2264 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2265 // assignment:
2266 // | NAME ':' expression ['=' annotated_rhs ]
2267 // | single_target ':' expression ['=' annotated_rhs ]
2268 // | (star_targets '=' )+ (yield_expr | star_expressions) !'=' [TYPE_COMMENT]
2269 // | single_target augassign ~ (yield_expr | star_expressions)
2270 //
2271 // single_target:
2272 // | single_subscript_attribute_target
2273 // | NAME
2274 // | '(' single_target ')'
2275 //
2276 // single_subscript_attribute_target:
2277 // | t_primary '.' NAME !t_lookahead
2278 // | t_primary '[' slices ']' !t_lookahead
2279 //
2280 // star_targets:
2281 // | star_target !','
2282 // | star_target (',' star_target )* [',']
2283
2284 // star_target:
2285 // | '*' (!'*' star_target)
2286 // | target_with_star_atom
2287 // target_with_star_atom:
2288 // | t_primary '.' NAME !t_lookahead
2289 // | t_primary '[' slices ']' !t_lookahead
2290 // | star_atom
2291 // star_atom:
2292 // | NAME
2293 // | '(' target_with_star_atom ')'
2294 // | '(' [star_targets_tuple_seq] ')'
2295 // | '[' [star_targets_list_seq] ']'
2296 // star_targets_list_seq: ','.star_target+ [',']
2297 // star_targets_tuple_seq:
2298 // | star_target (',' star_target )+ [',']
2299 // | star_target ','
2300
2301 // star_expressions
2302 //
2303
2304 // clang-format on
2305 case tok_comment: return parse_comment_stmt(parent, depth);
2306 286 case tok_return: return parse_return(parent, depth);
2307 30 case tok_import: return parse_import(parent, depth);
2308 44 case tok_from: return parse_import_from(parent, depth);
2309 16 case tok_raise: return parse_raise(parent, depth);
2310 301 case tok_pass: return parse_pass(parent, depth);
2311 9 case tok_del: return parse_del(parent, depth);
2312 30 case tok_yield: return parse_yield_stmt(parent, depth);
2313 20 case tok_assert: return parse_assert(parent, depth);
2314 6 case tok_break: return parse_break(parent, depth);
2315 7 case tok_continue: return parse_continue(parent, depth);
2316 6 case tok_global: return parse_global(parent, depth);
2317 6 case tok_nonlocal: return parse_nonlocal(parent, depth);
2318 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2319
2320 // Compound Statement
2321 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2322 // def <name>(...
2323 216 case tok_def: return parse_function_def(parent, false, depth);
2324 // async def <name>(...
2325 case tok_async: return parse_function_def(parent, true, depth);
2326 33 case tok_if: return parse_if_alt(parent, depth);
2327 76 case tok_class: return parse_class_def(parent, depth);
2328 52 case tok_with: return parse_with(parent, depth);
2329
2330 // Async for: only valid inside async function
2331 48 case tok_for: return parse_for(parent, depth);
2332 35 case tok_try: return parse_try(parent, depth);
2333 25 case tok_while: return parse_while(parent, depth);
2334 141 case tok_match: return parse_match(parent, depth);
2335 }
2336
2337 1006 auto expr = parse_expression(parent, depth);
2338 TRACE_START();
2339
2340 // allow unpacking
2341 // promote to a tuple expression
2342
2/2
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 840 times.
887 if (token().type() == tok_comma) {
2343 47 next_token();
2344 47 expr = parse_literal<TupleExpr>(this, parent, expr, 0, depth);
2345 }
2346
2347
4/4
✓ Branch 2 taken 342 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 115 times.
✓ Branch 5 taken 393 times.
876 switch (token().type()) {
2348 // <expr> = <>
2349 342 case tok_assign: return parse_assign(parent, expr, depth);
2350 // <expr> += <>
2351 26 case tok_augassign: return parse_augassign(parent, expr, depth);
2352 // <expr>: type = <>
2353 115 case ':':
2354 115 case tok_annassign: return parse_annassign(parent, expr, depth);
2355 }
2356
2357 // fallback to standard expression
2358 393 auto stmt_expr = parent->new_object<Expr>();
2359 393 stmt_expr->value = expr;
2360 TRACE_END();
2361 393 return stmt_expr;
2362 }
2363
2364 // Precedence climbing method
2365 // I liked shunting yard algorithm better has it was not recursive
2366 // but it got issues with some edge cases.
2367 //
2368 // https://en.wikipedia.org/wiki/Operator-precedence_parser#:~:text=The%20precedence%20climbing%20method%20is%20a%20compact%2C%20efficient%2C,in%20EBNF%20format%20will%20usually%20look%20like%20this%3A
2369 ExprNode* Parser::parse_operators(Node* og_parent, ExprNode* lhs, int min_precedence, int depth) {
2370 TRACE_START();
2371
2372 299 Node* parent = og_parent;
2373 299 BinOp* binop = nullptr;
2374 299 Compare* comp = nullptr;
2375 299 BoolOp* boolop = nullptr;
2376
2377 // FIXME: For error reporting we need to catch th error here and build the partia expression
2378 while (true) {
2379
2/2
✓ Branch 1 taken 565 times.
✓ Branch 4 taken 565 times.
565 Token lookahead = token();
2380
1/1
✓ Branch 1 taken 565 times.
565 OpConfig const& op_conf = get_operator_config(lookahead);
2381 565 int oppred = op_conf.precedence;
2382
2383
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 309 times.
565 if (op_conf.type == tok_eof) {
2384 256 return lhs;
2385 }
2386
2387 // lookahead is a binary operator whose precedence is >= min_precedence
2388
5/6
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 299 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 299 times.
309 if (!(is_binary_operator_family(op_conf) && oppred >= min_precedence)) {
2389 10 break;
2390 }
2391
2392 // we are going to build the operator for sure
2393 // create the operator right away so we can use save what we have so far for error reporting
2394
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 145 times.
299 if (op_conf.binarykind != BinaryOperator::None) {
2395
1/1
✓ Branch 1 taken 154 times.
154 binop = parent->new_object<BinOp>();
2396 154 binop->left = lhs;
2397 154 binop->op = op_conf.binarykind;
2398
2399 154 parent = binop;
2400 }
2401
2402
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 34 times.
145 else if (op_conf.cmpkind != CmpOperator::None) {
2403 // parent is a Comparison (1 < ?expr < ) and we are doing chained comparison
2404
1/1
✓ Branch 1 taken 111 times.
111 Compare* lhs_parent = cast<Compare>(parent);
2405
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 89 times.
111 if (lhs_parent != nullptr) {
2406 22 comp = lhs_parent;
2407
2/3
✓ Branch 1 taken 22 times.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
22 if (comp->safe_comparator_add(lhs)) {
2408
1/1
✓ Branch 1 taken 22 times.
22 comp->ops.push_back(op_conf.cmpkind);
2409 } else {
2410 ParsingError& err = parser_kwerror( //
2411 LOC, //
2412 "SyntaxError", //
2413 fmtstr("Unable to parse comparators") //
2414 );
2415 add_wip_expr(err, parent);
2416 PARSER_THROW(SyntaxError, err);
2417 }
2418 } else {
2419
1/1
✓ Branch 1 taken 89 times.
89 comp = parent->new_object<Compare>();
2420 89 comp->left = lhs;
2421
1/1
✓ Branch 1 taken 89 times.
89 comp->ops.push_back(op_conf.cmpkind);
2422 }
2423
2424 111 parent = comp;
2425 }
2426
2427
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 else if (op_conf.boolkind != BoolOperator::None) {
2428
1/1
✓ Branch 1 taken 34 times.
34 BoolOp* lhs_parent = cast<BoolOp>(parent);
2429
2430
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
34 if (lhs_parent != nullptr && lhs_parent->op == op_conf.boolkind) {
2431 7 boolop = lhs_parent;
2432
2433
2/3
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
7 if (boolop->safe_value_add(lhs)) {
2434 7 boolop->opcount += 1;
2435 } else {
2436 ParsingError& err = parser_kwerror( //
2437 LOC, //
2438 "SyntaxError", //
2439 fmtstr("Unable to finish parsing bool operator") //
2440 );
2441 add_wip_expr(err, parent);
2442 PARSER_THROW(SyntaxError, err);
2443 }
2444
2445 7 } else {
2446
1/1
✓ Branch 1 taken 27 times.
27 boolop = parent->new_object<BoolOp>();
2447 27 boolop->op = op_conf.boolkind;
2448
1/1
✓ Branch 1 taken 27 times.
27 boolop->values = {lhs};
2449 27 boolop->opcount = 1;
2450 }
2451
2452 34 parent = boolop;
2453 }
2454
2455
1/1
✓ Branch 1 taken 299 times.
299 next_token();
2456 // in the case of 1 < 2 < 3
2457
2458
1/1
✓ Branch 1 taken 266 times.
299 auto* rhs = parse_expression(parent, depth);
2459
2/2
✓ Branch 1 taken 266 times.
✓ Branch 4 taken 266 times.
266 lookahead = token();
2460
2461
1/1
✓ Branch 1 taken 266 times.
266 auto lookconf = get_operator_config(lookahead);
2462 266 auto lookpred = lookconf.precedence;
2463 266 auto right_assoc = !lookconf.left_associative;
2464
2465 // lookahead is a binary operator whose precedence is greater
2466 // than op's, or a right-associative operator
2467 // whose precedence is equal to op's
2468
2/8
✗ Branch 1 not taken.
✓ Branch 2 taken 266 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 266 times.
266 while (lookahead.type() == tok_operator && is_binary_operator_family(lookconf) &&
2469 (lookpred > oppred || (right_assoc && lookpred == oppred))) {
2470 rhs = parse_expression_1(parent, rhs, oppred, depth + 1);
2471
2472 lookahead = token();
2473
2474 lookconf = get_operator_config(lookahead);
2475 lookpred = lookconf.precedence;
2476 right_assoc = !lookconf.left_associative;
2477 }
2478
2479 // the result of applying op with operands lhs and rhs
2480
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 126 times.
266 if (op_conf.binarykind != BinaryOperator::None) {
2481 140 binop->right = rhs;
2482 140 lhs = binop;
2483
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 29 times.
126 } else if (op_conf.cmpkind != CmpOperator::None) {
2484 // rhs can be comp if it was a nested comparison
2485 // but it does not have to be
2486
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 19 times.
97 if (rhs != comp) {
2487
1/1
✓ Branch 1 taken 78 times.
78 comp->safe_comparator_add(rhs);
2488 }
2489 //
2490 97 lhs = comp;
2491
2492
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 } else if (op_conf.boolkind != BoolOperator::None) {
2493
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 6 times.
29 if (rhs != boolop) {
2494
1/1
✓ Branch 1 taken 23 times.
23 boolop->values.push_back(rhs);
2495 }
2496 29 lhs = boolop;
2497 } else {
2498 kwerror("unknow operator {}", str(op_conf));
2499 }
2500 831 }
2501
2502 TRACE_END();
2503 10 return lhs;
2504 }
2505
2506 Comment* Parser::parse_comment(Node* parent, int depth) {
2507 TRACE_START();
2508
2509 278 Comment* com = parent->new_object<Comment>();
2510 assert(token().type() == tok_comment, "Need a comment token");
2511
2512 278 com->comment = token().identifier();
2513 278 next_token();
2514
2515 // while (!in(token().type(), tok_newline, tok_eof)) {
2516 // com->tokens.push_back(token());
2517 // next_token();
2518 // }
2519
2520 278 return com;
2521 }
2522
2523 ExprNode* Parser::parse_expression(Node* parent, int depth, bool comma) {
2524 TRACE_START();
2525
2526 4206 expression_depth += 1;
2527 // parse primary
2528 4206 auto primary = parse_expression_primary(parent, depth);
2529
2530
3/3
✓ Branch 2 taken 175 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 3644 times.
3868 switch (token().type()) {
2531
2532 // <expr>(args...)
2533 175 case tok_parens: {
2534 175 primary = parse_call(parent, primary, depth);
2535 151 break;
2536 }
2537
2538 // <expr>.<identifier>
2539 49 case tok_dot: {
2540 49 primary = parse_attribute(parent, primary, depth);
2541 45 break;
2542 }
2543 }
2544
2545 3840 primary = parse_expression_1(parent, primary, 0, depth, comma);
2546
2547 3786 expression_depth -= 1;
2548 3786 return primary;
2549 }
2550
2551 // Expression we can guess rightaway from the current token we are seeing
2552 ExprNode* Parser::parse_expression_primary(Node* parent, int depth) {
2553
2554
11/13
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3580 times.
✓ Branch 5 taken 644 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 56 times.
✓ Branch 8 taken 53 times.
✓ Branch 9 taken 124 times.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 39 times.
✓ Branch 14 taken 248 times.
4779 switch (token().type()) {
2555 // await <expr>
2556 7 case tok_await: return parse_await(parent, depth);
2557
2558 // yield from <expr>
2559 // yield <expr>
2560 case tok_yield_from:
2561 case tok_yield: return parse_yield(parent, depth);
2562
2563 // atom:
2564 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2565 // Name: <identifier>
2566 3580 case tok_identifier: return parse_name(parent, depth);
2567
2568 644 case tok_none:
2569 case tok_true:
2570 case tok_false:
2571 case tok_int:
2572 case tok_float:
2573 644 case tok_string: return parse_constant(parent, depth);
2574 18 case tok_formatstr: return parse_special_string(parent, depth);
2575
2576 // List: [a, b]
2577 // Comprehension [a for a in b]
2578 56 case tok_square: return parse_list(parent, depth);
2579
2580 // Tuple: (a, b)
2581 // Generator Comprehension: (a for a in b)
2582 // can be (1 + b)
2583 53 case tok_parens: return parse_tuple_generator(parent, depth);
2584
2585 // Set: {a, b}
2586 // Comprehension {a for a in b}
2587 // OR
2588 // Dict: {a : b}
2589 // Comprehension {a: b for a, b in c}
2590 124 case tok_curly: return parse_set_dict(parent, depth);
2591
2592 // TODO: add elipsis
2593
2594 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2595 // lambda <name>:
2596 9 case tok_lambda: return parse_lambda(parent, depth);
2597
2598 // f"
2599 case tok_fstring: return parse_joined_string(parent, depth);
2600
2601 // not python syntax
2602 // if <expr> else <expr>
2603 1 case tok_if: {
2604
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (with_extension)
2605 1 return parse_ifexp_ext(parent, depth);
2606 }
2607
2608 // *<expr>
2609 case tok_star:
2610 39 case tok_operator: return parse_prefix_unary(parent, depth);
2611 }
2612
2613 // Left Unary operator
2614 // + <expr> | - <expr> | ! <expr> | ~ <expr>
2615
2616
2/2
✓ Branch 2 taken 248 times.
✓ Branch 6 taken 248 times.
496 ParsingError& error = parser_kwerror( //
2617 LOC, //
2618 "SyntaxError", //
2619 // fmtstr("Could not deduce the expression {}", str(TokenType(token().type()))) //
2620 "Expected an expression" //
2621 );
2622 248 add_wip_expr(error, parent);
2623
1/1
✓ Branch 2 taken 248 times.
248 PARSER_THROW(SyntaxError, error);
2624 }
2625
2626 ExprNode* Parser::parse_expression_1(
2627 Node* parent, ExprNode* primary, int min_precedence, int depth, bool comma) {
2628 //
2629
7/8
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 299 times.
✓ Branch 6 taken 21 times.
✓ Branch 7 taken 524 times.
✓ Branch 8 taken 580 times.
✓ Branch 9 taken 2368 times.
3849 switch (token().type()) {
2630 // <expr> := <expr>
2631 // assign expression instead of the usual assign statement
2632 7 case tok_walrus: return parse_named_expr(parent, primary, depth);
2633
2634 // <expr> boolop <expr>
2635 /*
2636 case tok_boolop:
2637 return parse_bool_operator(parent, primary, depth);
2638 case tok_binaryop:
2639 return parse_binary_operator(parent, primary, depth);
2640 case tok_compareop:
2641 return parse_compare_operator(parent, primary, depth);
2642 */
2643 case tok_unaryop: return parse_suffix_unary(parent, primary, depth);
2644
2645 50 case tok_if: return parse_ifexp(parent, primary, depth);
2646 299 case tok_in:
2647 299 case tok_operator: return parse_operators(parent, primary, min_precedence, depth);
2648
2649 // <expr>[
2650 21 case tok_square: return parse_subscript(parent, primary, depth);
2651
2652 // this causes more issues than it solves
2653 // to allow unpacking we will need to move this to somewhere more specific
2654 524 case tok_comma: {
2655 // If we are going deeper we neeed the user to use ( explicitly
2656
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 489 times.
524 if (comma) {
2657 35 next_token();
2658
2659 35 auto expr = parse_literal<TupleExpr>(this, parent, primary, '\0', depth);
2660 29 return expr;
2661 }
2662 }
2663
2664 // ':' is only valid inside a subscript
2665 case ':': {
2666
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 1051 times.
1069 if (allow_slice())
2667 18 return parse_slice(parent, primary, depth);
2668 }
2669 }
2670
2671 3419 return primary;
2672 }
2673
2674 ExprNode* Parser::parse_special_string(Node* parent, int depth) {
2675 TRACE_START();
2676
2677
2/2
✓ Branch 1 taken 18 times.
✓ Branch 5 taken 18 times.
18 String format_type = token().identifier();
2678
2679
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 if (format_type == "f") {
2680
1/1
✓ Branch 1 taken 18 times.
18 return parse_joined_string(parent, depth);
2681 }
2682
2683 if (format_type == "b") {
2684 next_token();
2685 return parse_constant(parent, depth);
2686 }
2687
2688 if (format_type == "r") {
2689 next_token();
2690 return parse_constant(parent, depth);
2691 }
2692
2693 return nullptr;
2694 18 }
2695
2696 struct SetLexerMode {
2697 SetLexerMode(AbstractLexer& lexer, LexerMode mode): lexer(lexer) {
2698 58 old_mode = int(lexer.get_mode());
2699 58 lexer.set_mode(int(mode));
2700 58 }
2701
2702 ~SetLexerMode() { lexer.set_mode(old_mode); }
2703
2704 int old_mode;
2705 AbstractLexer& lexer;
2706 };
2707
2708 // FIXME: this can be simplified if the fmtstr lexer tokenize more
2709 ExprNode* Parser::parse_joined_string(Node* parent, int depth) {
2710
2/2
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
18 Token tok = token(); // `f`
2711
2712
1/1
✓ Branch 1 taken 18 times.
18 JoinedStr* expr = parent->new_object<JoinedStr>();
2713
4/5
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
18 start_code_loc(expr, token());
2714 int8 endquote;
2715
2716 {
2717
1/1
✓ Branch 1 taken 18 times.
18 SetLexerMode _(_lex, LexerMode::Character);
2718
2/2
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
18 tok = next_token(); // Quote
2719
1/1
✓ Branch 1 taken 18 times.
18 endquote = token().type();
2720
2721
2/2
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
18 tok = next_token();
2722 18 String buffer;
2723
2724 auto pushbuffer = [&]() {
2725
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 13 times.
33 if (!buffer.empty()) {
2726 20 Constant* cst = expr->new_object<Constant>();
2727
3/3
✓ Branch 1 taken 20 times.
✓ Branch 4 taken 20 times.
✓ Branch 7 taken 20 times.
20 cst->value = ConstantValue(buffer);
2728
1/1
✓ Branch 1 taken 20 times.
20 expr->values.push_back(cst);
2729 20 buffer.clear();
2730 }
2731 33 };
2732
2733
2/2
✓ Branch 1 taken 115 times.
✓ Branch 2 taken 18 times.
133 while (tok.type() != endquote) {
2734
2735
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 95 times.
115 if (tok.type() == '{') {
2736
1/1
✓ Branch 1 taken 20 times.
20 char c = _lex.peekc();
2737
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (c == '{') {
2738
1/1
✓ Branch 1 taken 5 times.
5 buffer.push_back('{');
2739
1/1
✓ Branch 1 taken 5 times.
5 buffer.push_back('{');
2740
2741
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 tok = next_token();
2742
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 tok = next_token();
2743 5 continue;
2744 }
2745
2746
1/1
✓ Branch 1 taken 15 times.
15 pushbuffer();
2747 // Parse FormattedValue
2748
2/2
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
15 expr->values.push_back(parse_formatted_value_string(expr, depth + 1));
2749
2/2
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
15 tok = token();
2750 15 continue;
2751 15 }
2752
2753
1/1
✓ Branch 2 taken 95 times.
95 buffer.push_back(tok.type());
2754
2/2
✓ Branch 1 taken 95 times.
✓ Branch 4 taken 95 times.
95 tok = next_token();
2755 }
2756
1/1
✓ Branch 1 taken 18 times.
18 pushbuffer();
2757 18 }
2758
2759
4/5
✓ Branch 1 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
18 end_code_loc(expr, token());
2760 expect_token(endquote, true, expr, LOC);
2761 18 return expr;
2762 18 }
2763
2764 ExprNode* Parser::parse_formatted_value_string(Node* parent, int depth) {
2765 // {<value>(:<formatspec>)?}
2766 TRACE_START();
2767
2768 15 FormattedValue* expr = parent->new_object<FormattedValue>();
2769
4/5
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 15 times.
15 start_code_loc(expr, token());
2770
2771 {
2772
1/1
✓ Branch 1 taken 15 times.
15 SetLexerMode _(_lex, LexerMode::Default);
2773 expect_token('{', true, expr, LOC);
2774
1/1
✓ Branch 1 taken 15 times.
15 expr->value = parse_expression(expr, depth + 1);
2775 15 }
2776
2777
1/2
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 if (token().type() == ':') {
2778 15 next_token(); // eat ':' so we get next character
2779 15 expr->format_spec = parse_format_spec(expr, depth);
2780 }
2781
2782
4/5
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 15 times.
15 end_code_loc(expr, token());
2783 expect_token('}', true, expr, LOC);
2784
2785 15 return expr;
2786 }
2787
2788 JoinedStr* Parser::parse_format_spec(Node* parent, int depth) {
2789 // [[fill]align][sign][#][0][minimumwidth][.precision][type]
2790 // https://peps.python.org/pep-3101/
2791 TRACE_START();
2792
2793 // str{<something>}end
2794
1/1
✓ Branch 1 taken 15 times.
15 JoinedStr* expr = parent->new_object<JoinedStr>();
2795
4/5
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 15 times.
15 start_code_loc(expr, token());
2796
2797 15 String buffer;
2798
2799 auto pushbuffer = [&]() {
2800
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 10 times.
25 if (!buffer.empty()) {
2801 15 Constant* cst = expr->new_object<Constant>();
2802
3/3
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
✓ Branch 7 taken 15 times.
15 cst->value = ConstantValue(buffer);
2803
1/1
✓ Branch 1 taken 15 times.
15 expr->values.push_back(cst);
2804 15 buffer.clear();
2805 }
2806 25 };
2807
2808 // Get Current token
2809
1/1
✓ Branch 1 taken 15 times.
15 char c = token().type();
2810 15 bool first = true;
2811
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 15 times.
45 while (c != '}') {
2812
2813
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 20 times.
30 if (c == '{') {
2814
1/1
✓ Branch 1 taken 10 times.
10 pushbuffer();
2815 {
2816
1/1
✓ Branch 1 taken 10 times.
10 SetLexerMode _(_lex, LexerMode::Default);
2817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!first) {
2818 next_token(); // token is now {
2819 }
2820 expect_token('{', true, expr, LOC);
2821
2/2
✓ Branch 1 taken 10 times.
✓ Branch 4 taken 10 times.
10 expr->values.push_back(parse_expression(expr, depth + 1));
2822 10 }
2823
2824 expect_token('}', true, expr, LOC);
2825
1/1
✓ Branch 1 taken 10 times.
10 c = token().type();
2826 10 first = true;
2827 10 continue;
2828 10 }
2829
2830
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (!first) {
2831
1/1
✓ Branch 1 taken 5 times.
5 c = next_token().type();
2832 }
2833
1/1
✓ Branch 1 taken 20 times.
20 buffer.push_back(c);
2834
1/1
✓ Branch 1 taken 20 times.
20 c = _lex.peekc();
2835 20 first = false;
2836 }
2837
2838
1/1
✓ Branch 1 taken 15 times.
15 pushbuffer();
2839
2840
1/1
✓ Branch 1 taken 15 times.
15 next_token(); // Current token becomes '}'
2841
2842 {
2843
1/1
✓ Branch 1 taken 15 times.
15 SetLexerMode _(_lex, LexerMode::Default);
2844 expect_token('}', false, expr, LOC);
2845 15 }
2846 15 return expr;
2847 15 }
2848
2849 Token const& Parser::next_token() {
2850 // add current token to the line and fetch next one
2851 COZ_BEGIN("T::Lexer::next_token");
2852
2853 // desindent are issued right after newlines
2854
2/2
✓ Branch 1 taken 19696 times.
✓ Branch 5 taken 19696 times.
19696 is_empty_line = in(token().type(), tok_newline, tok_desindent, tok_indent);
2855
2856 19696 currentline.add(token());
2857 19696 Token const& tok = _lex.next_token();
2858
2859 COZ_PROGRESS_NAMED("Lexer::next_token");
2860 COZ_END("T::Lexer::next_token");
2861 19696 return tok;
2862 }
2863
2864 } // namespace lython
2865