| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "parsing_error.h" | ||
| 2 | |||
| 3 | #include "ast/magic.h" | ||
| 4 | #include "ast/ops.h" | ||
| 5 | #include "lexer/lexer.h" | ||
| 6 | #include "lexer/unlex.h" | ||
| 7 | #include "utilities/strings.h" | ||
| 8 | |||
| 9 | namespace lython { | ||
| 10 | |||
| 11 | ParsingError::ParsingError(Array<int> expected, Token token, Node* obj, CodeLocation loc): | ||
| 12 | ✗ | ParsingError(expected, token, loc) { | |
| 13 | ✗ | switch (obj->family()) { | |
| 14 | ✗ | case NodeFamily::Expression: expr = (ExprNode*)obj; | |
| 15 | ✗ | case NodeFamily::Pattern: pat = (Pattern*)obj; | |
| 16 | ✗ | case NodeFamily::Statement: stmt = (StmtNode*)obj; | |
| 17 | ✗ | default: break; | |
| 18 | } | ||
| 19 | ✗ | } | |
| 20 | |||
| 21 | void add_wip_expr(ParsingError& err, StmtNode* stmt) { err.stmt = stmt; } | ||
| 22 | |||
| 23 | void add_wip_expr(ParsingError& err, ExprNode* expr) { err.expr = expr; } | ||
| 24 | |||
| 25 | void add_wip_expr(ParsingError& err, Node* expr) { | ||
| 26 |
4/4✓ Branch 1 taken 124 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 346 times.
✓ Branch 4 taken 67 times.
|
565 | switch (expr->family()) { |
| 27 | 124 | case NodeFamily::Expression: err.expr = (ExprNode*)expr; | |
| 28 | 152 | case NodeFamily::Pattern: err.pat = (Pattern*)expr; | |
| 29 | 498 | case NodeFamily::Statement: err.stmt = (StmtNode*)expr; | |
| 30 | 565 | default: break; | |
| 31 | } | ||
| 32 | 565 | } | |
| 33 | |||
| 34 | Node* get_expr(ParsingError const& error) { | ||
| 35 |
2/2✓ Branch 0 taken 498 times.
✓ Branch 1 taken 67 times.
|
565 | if (error.stmt) { |
| 36 | 498 | return error.stmt; | |
| 37 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | } else if (error.expr) { |
| 38 | ✗ | return error.expr; | |
| 39 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | } else if (error.pat) { |
| 40 | ✗ | return error.pat; | |
| 41 | } | ||
| 42 | 67 | return nullptr; | |
| 43 | } | ||
| 44 | |||
| 45 | CommonAttributes* get_code_loc(ParsingError const& error) { | ||
| 46 |
2/2✓ Branch 0 taken 498 times.
✓ Branch 1 taken 67 times.
|
565 | if (error.stmt) { |
| 47 |
1/2✓ Branch 0 taken 498 times.
✗ Branch 1 not taken.
|
498 | return error.stmt; |
| 48 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | } else if (error.expr) { |
| 49 | ✗ | return error.expr; | |
| 50 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | } else if (error.pat) { |
| 51 | ✗ | return error.pat; | |
| 52 | } | ||
| 53 | 67 | return nullptr; | |
| 54 | } | ||
| 55 | |||
| 56 | String get_parent(ParsingError const& error) { | ||
| 57 |
2/2✓ Branch 0 taken 498 times.
✓ Branch 1 taken 67 times.
|
565 | if (error.stmt) { |
| 58 | 498 | return shortprint(get_parent(error.stmt)); | |
| 59 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | } else if (error.expr) { |
| 60 | ✗ | return shortprint(get_parent(error.expr)); | |
| 61 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | } else if (error.pat) { |
| 62 | ✗ | return shortprint(get_parent(error.pat)); | |
| 63 | } | ||
| 64 | |||
| 65 |
1/1✓ Branch 2 taken 67 times.
|
67 | return "<module>"; |
| 66 | } | ||
| 67 | |||
| 68 | String get_filename(ParsingErrorPrinter* printer) { | ||
| 69 | ✗ | if (printer->lexer) { | |
| 70 | ✗ | return printer->lexer->file_name(); | |
| 71 | } | ||
| 72 | ✗ | return "<input>"; | |
| 73 | } | ||
| 74 | |||
| 75 | void ParsingErrorPrinter::print_ast(ParsingError const& error, | ||
| 76 | Node* node, | ||
| 77 | CommonAttributes* srcloc) { | ||
| 78 | // Print what we were able to parse | ||
| 79 | { | ||
| 80 | ✗ | bool written = false; | |
| 81 | |||
| 82 | ✗ | if (node) { | |
| 83 | ✗ | auto noline_buf = NoNewLine(out); | |
| 84 | ✗ | std::ostream noline(&noline_buf); | |
| 85 | ✗ | codeline(); | |
| 86 | ✗ | noline << str(node); | |
| 87 | ✗ | noline.flush(); | |
| 88 | ✗ | written = true; | |
| 89 | ✗ | } | |
| 90 | |||
| 91 | // Print the tokens that we were not able to parse | ||
| 92 | ✗ | if (error.remaining.size() > 0) { | |
| 93 | ✗ | Unlex unlex; | |
| 94 | ✗ | unlex.format(out, error.remaining); | |
| 95 | ✗ | written = true; | |
| 96 | } | ||
| 97 | |||
| 98 | ✗ | if (written) { | |
| 99 | // Underline error if possible | ||
| 100 | ✗ | if (srcloc) { | |
| 101 | ✗ | underline(*srcloc); | |
| 102 | } else { | ||
| 103 | ✗ | underline(error.received_token); | |
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | ✗ | } | |
| 108 | |||
| 109 | void ParsingErrorPrinter::print_tok(ParsingError const& error, CommonAttributes* srcloc) { | ||
| 110 | 565 | Unlex unlex; | |
| 111 | |||
| 112 |
1/1✓ Branch 1 taken 565 times.
|
565 | codeline(); |
| 113 |
1/1✓ Branch 1 taken 565 times.
|
565 | unlex.format(out, error.line); |
| 114 | |||
| 115 | // Underline error if possible | ||
| 116 |
1/1✓ Branch 1 taken 565 times.
|
565 | underline(error.received_token); |
| 117 | 565 | } | |
| 118 | |||
| 119 | void ParsingErrorPrinter::print(ParsingError const& error) { | ||
| 120 |
1/1✓ Branch 1 taken 565 times.
|
565 | String filename = get_filename(); |
| 121 | 565 | Node* node = get_expr(error); | |
| 122 | 565 | CommonAttributes* srcloc = get_code_loc(error); | |
| 123 |
1/1✓ Branch 1 taken 565 times.
|
565 | String parent = get_parent(error); |
| 124 | |||
| 125 | 565 | int line = error.received_token.line(); | |
| 126 | |||
| 127 |
7/7✓ Branch 1 taken 565 times.
✓ Branch 4 taken 565 times.
✓ Branch 7 taken 565 times.
✓ Branch 10 taken 565 times.
✓ Branch 13 taken 565 times.
✓ Branch 16 taken 565 times.
✓ Branch 19 taken 565 times.
|
565 | firstline() << "File \"" << filename << "\", line " << line << ", in " << parent; |
| 128 | |||
| 129 | // Lython own code loc | ||
| 130 | #if WITH_LOG | ||
| 131 |
1/2✓ Branch 0 taken 565 times.
✗ Branch 1 not taken.
|
565 | if (with_compiler_code_loc) { |
| 132 |
3/3✓ Branch 1 taken 565 times.
✓ Branch 4 taken 565 times.
✓ Branch 7 taken 565 times.
|
565 | newline() << error.loc.repr(); |
| 133 | } | ||
| 134 | #endif | ||
| 135 | |||
| 136 | // Error message | ||
| 137 | if (false) { | ||
| 138 | print_ast(error, node, srcloc); | ||
| 139 | } else { | ||
| 140 |
1/1✓ Branch 1 taken 565 times.
|
565 | print_tok(error, srcloc); |
| 141 | } | ||
| 142 | |||
| 143 |
3/3✓ Branch 1 taken 565 times.
✓ Branch 4 taken 565 times.
✓ Branch 7 taken 565 times.
|
565 | errorline() << error.error_kind << ": "; |
| 144 |
2/2✓ Branch 1 taken 251 times.
✓ Branch 2 taken 314 times.
|
565 | if (error.expected_tokens.size() > 0) { |
| 145 | 251 | Array<String> toks; | |
| 146 |
2/2✓ Branch 1 taken 251 times.
✓ Branch 5 taken 251 times.
|
502 | std::transform(std::begin(error.expected_tokens), |
| 147 | 251 | std::end(error.expected_tokens), | |
| 148 | std::back_inserter(toks), | ||
| 149 | [](int tok) -> String { return to_human_name(tok); }); | ||
| 150 | |||
| 151 |
2/2✓ Branch 2 taken 251 times.
✓ Branch 5 taken 251 times.
|
251 | String expected = join("|", toks); |
| 152 | |||
| 153 |
5/5✓ Branch 1 taken 251 times.
✓ Branch 4 taken 251 times.
✓ Branch 7 taken 251 times.
✓ Branch 11 taken 251 times.
✓ Branch 14 taken 251 times.
|
251 | out << "Expected: " << expected << " token but got " << to_human_name(error.received_token); |
| 154 | 251 | } else { | |
| 155 |
1/1✓ Branch 1 taken 314 times.
|
314 | out << error.message; |
| 156 | } | ||
| 157 | |||
| 158 |
1/1✓ Branch 1 taken 565 times.
|
565 | end(); |
| 159 | 565 | } | |
| 160 | |||
| 161 | String shortprint(Node const* node) { | ||
| 162 |
2/2✓ Branch 0 taken 99 times.
✓ Branch 1 taken 532 times.
|
631 | if (node->kind == NodeKind::FunctionDef) { |
| 163 | 99 | FunctionDef const* fun = static_cast<FunctionDef const*>(node); | |
| 164 | 99 | return str(fun->name); | |
| 165 | } | ||
| 166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 532 times.
|
532 | if (node->kind == NodeKind::ClassDef) { |
| 167 | ✗ | ClassDef const* def = static_cast<ClassDef const*>(node); | |
| 168 | ✗ | return str(def->name); | |
| 169 | } | ||
| 170 |
2/2✓ Branch 0 taken 524 times.
✓ Branch 1 taken 8 times.
|
532 | if (node->kind == NodeKind::Module) { |
| 171 |
1/1✓ Branch 2 taken 524 times.
|
524 | return "<module>"; |
| 172 | } | ||
| 173 | 8 | return str(node); | |
| 174 | } | ||
| 175 | |||
| 176 | Node const* get_parent(Node const* parent) { | ||
| 177 | 623 | Node const* n = parent->get_parent(); | |
| 178 | 623 | Node const* p = parent; | |
| 179 | |||
| 180 |
1/2✓ Branch 0 taken 711 times.
✗ Branch 1 not taken.
|
711 | while (n != nullptr) { |
| 181 | |||
| 182 |
2/2✓ Branch 0 taken 524 times.
✓ Branch 1 taken 187 times.
|
711 | if (n->kind == NodeKind::Module) { |
| 183 | 524 | return n; | |
| 184 | } | ||
| 185 | |||
| 186 |
2/2✓ Branch 0 taken 99 times.
✓ Branch 1 taken 88 times.
|
187 | if (n->kind == NodeKind::FunctionDef) { |
| 187 | 99 | return n; | |
| 188 | } | ||
| 189 | 88 | p = n; | |
| 190 | 88 | n = n->get_parent(); | |
| 191 | } | ||
| 192 | |||
| 193 | ✗ | return p; | |
| 194 | } | ||
| 195 | |||
| 196 | } // namespace lython | ||
| 197 |