| 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 |