aboutsummaryrefslogtreecommitdiff
path: root/src/yuescript/yue_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuescript/yue_parser.cpp')
-rw-r--r--src/yuescript/yue_parser.cpp90
1 files changed, 64 insertions, 26 deletions
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index f564f6a..ad76517 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -1342,40 +1342,78 @@ std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCo
1342 return buf.str(); 1342 return buf.str();
1343 } 1343 }
1344 const int ASCII = 255; 1344 const int ASCII = 255;
1345 int length = errLine; 1345 const int contextLines = 2;
1346 auto begin = codes->begin(); 1346
1347 auto end = codes->end(); 1347 std::vector<std::pair<input::iterator, input::iterator>> lines;
1348 int count = 0; 1348 auto lineStart = codes->begin();
1349
1349 for (auto it = codes->begin(); it != codes->end(); ++it) { 1350 for (auto it = codes->begin(); it != codes->end(); ++it) {
1350 if (*it == '\n') { 1351 if (*it == '\n') {
1351 if (count + 1 == length) { 1352 lines.emplace_back(lineStart, it);
1352 end = it; 1353 lineStart = it + 1;
1353 break; 1354 }
1355 }
1356
1357 if (lineStart != codes->end()) {
1358 lines.emplace_back(lineStart, codes->end());
1359 }
1360
1361 int totalLines = static_cast<int>(lines.size());
1362 int startLine = std::max(1, errLine - contextLines);
1363 int endLine = std::min(totalLines, errLine + contextLines);
1364
1365 int maxLineNum = endLine + lineOffset;
1366 int lineNumWidth = 1;
1367 int temp = maxLineNum;
1368 while (temp >= 10) {
1369 temp /= 10;
1370 lineNumWidth++;
1371 }
1372
1373 std::ostringstream buf;
1374 buf << errLine + lineOffset << ": " << msg << '\n';
1375
1376 int errorDisplayCol = 0;
1377 if (errLine >= 1 && errLine <= totalLines) {
1378 auto& errorLineRange = lines[errLine - 1];
1379
1380 auto it = errorLineRange.first;
1381 int displayCol = 0;
1382 for (int i = 0; i < errCol && it != errorLineRange.second; ++i) {
1383 if (*it == '\t') {
1384 displayCol += 2;
1385 } else if (*it > ASCII) {
1386 displayCol += 2;
1354 } else { 1387 } else {
1355 begin = it + 1; 1388 displayCol++;
1356 } 1389 }
1357 count++; 1390 ++it;
1358 } 1391 }
1392 errorDisplayCol = displayCol;
1359 } 1393 }
1360 int oldCol = errCol; 1394
1361 int col = std::max(0, oldCol - 1); 1395 for (int lineNum = startLine; lineNum <= endLine; ++lineNum) {
1362 auto it = begin; 1396 int displayLineNum = lineNum + lineOffset;
1363 for (int i = 0; i < oldCol && it != end; ++i) { 1397 if (displayLineNum <= 0) continue;
1364 if (*it > ASCII) { 1398 std::string lineNumStr = std::to_string(displayLineNum);
1365 ++col; 1399
1400 int padding = lineNumWidth - static_cast<int>(lineNumStr.size());
1401 buf << std::string(padding, ' ') << lineNumStr << " | ";
1402
1403 if (lineNum >= 1 && lineNum <= totalLines) {
1404 auto& lineRange = lines[lineNum - 1];
1405 std::string line = utf8_encode({lineRange.first, lineRange.second});
1406 Utils::replace(line, "\t"sv, " "sv);
1407 buf << line;
1408 }
1409 buf << '\n';
1410
1411 if (lineNum == errLine) {
1412 buf << std::string(lineNumWidth, ' ') << " ";
1413 buf << std::string(errorDisplayCol - 1, ' ') << "^"sv << '\n';
1366 } 1414 }
1367 ++it;
1368 }
1369 auto line = utf8_encode({begin, end});
1370 while (col < static_cast<int>(line.size())
1371 && (line[col] == ' ' || line[col] == '\t')) {
1372 col++;
1373 } 1415 }
1374 Utils::replace(line, "\t"sv, " "sv); 1416
1375 std::ostringstream buf;
1376 buf << errLine + lineOffset << ": "sv << msg << '\n'
1377 << line << '\n'
1378 << std::string(col, ' ') << "^"sv;
1379 return buf.str(); 1417 return buf.str();
1380} 1418}
1381 1419