Skip to content

Commit 39a77d3

Browse files
committed
Initial control flow syntax highlighting implementation
1 parent 90051ce commit 39a77d3

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

gui/qt/datawidget.cpp

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,33 @@
33
#include "mainwindow.h"
44

55
#include <QtWidgets/QApplication>
6+
#include <QStringView>
7+
#include <QLatin1StringView>
8+
9+
#include <algorithm>
10+
#include <array>
11+
12+
13+
using namespace Qt::StringLiterals;
14+
15+
namespace {
16+
inline constexpr std::array controlFlowMnemonics {
17+
"CALL"_L1, "DJNZ"_L1, "JP"_L1, "JR"_L1, "RET"_L1, "RETI"_L1, "RETN"_L1, "RST"_L1
18+
};
19+
20+
inline constexpr std::array noTargetMnemonics {
21+
"RET"_L1, "RETI"_L1, "RETN"_L1
22+
};
23+
24+
inline constexpr std::array reservedTokens {
25+
"A"_L1, "B"_L1, "C"_L1, "D"_L1, "E"_L1, "H"_L1, "L"_L1, "I"_L1, "R"_L1,
26+
"AF"_L1, "BC"_L1, "DE"_L1, "HL"_L1, "SP"_L1,
27+
"IX"_L1, "IY"_L1, "IXH"_L1, "IXL"_L1,
28+
"IYH"_L1, "IYL"_L1, "MB"_L1,
29+
"NZ"_L1, "Z"_L1, "NC"_L1, "C"_L1,
30+
"PO"_L1, "PE"_L1, "P"_L1, "M"_L1
31+
};
32+
}
633

734
DataWidget::DataWidget(QWidget *parent) : QPlainTextEdit{parent} {
835
moveable = false;
@@ -143,6 +170,9 @@ AsmHighlighter::AsmHighlighter(QTextDocument *parent) : QSyntaxHighlighter(paren
143170

144171
mnemonicFormat.setForeground(QColor(darkMode ? "darkorange" : "darkblue"));
145172

173+
controlFlowFormat.setForeground(QColor("crimson"));
174+
controlFlowTargetFormat.setForeground(QColor("#dc795d"));
175+
146176
symbolFormat.setFontWeight(disasm.bold_sym ? QFont::DemiBold : QFont::Normal);
147177
rule.pattern = QRegularExpression("\\b\\w+\\b");
148178
rule.format = symbolFormat;
@@ -187,6 +217,18 @@ void AsmHighlighter::highlightBlock(const QString &text) {
187217
setFormat(match.capturedStart(4), match.capturedLength(4), breakPFormat);
188218
setFormat(match.capturedStart(5), match.capturedLength(5), bytesFormat);
189219
setFormat(match.capturedStart(6), match.capturedLength(6), mnemonicFormat);
220+
221+
const QString fullMnemonic = match.captured(6);
222+
const QString primary = fullMnemonic.section('.', 0, 0).toUpper();
223+
const QStringView pv{primary};
224+
225+
const bool isControlFlow = std::any_of(controlFlowMnemonics.begin(), controlFlowMnemonics.end(),
226+
[&](const QLatin1StringView tok){ return pv == tok; });
227+
228+
if (isControlFlow) {
229+
setFormat(match.capturedStart(6), match.capturedLength(6), controlFlowFormat);
230+
}
231+
190232
foreach(const HighlightingRule &rule, highlightingRules) {
191233
QRegularExpressionMatchIterator iter = rule.pattern.globalMatch(text, match.capturedEnd());
192234
while (iter.hasNext()) {
@@ -196,5 +238,47 @@ void AsmHighlighter::highlightBlock(const QString &text) {
196238
}
197239
}
198240
}
241+
242+
if (!isControlFlow) {
243+
return;
244+
}
245+
246+
if (std::any_of(noTargetMnemonics.begin(), noTargetMnemonics.end(),
247+
[&](const QLatin1StringView tok){ return pv == tok; })) {
248+
return;
249+
}
250+
251+
const int operandStart = match.capturedEnd();
252+
const QString operands = text.mid(operandStart);
253+
254+
// hex address patterns allowing optional +/ - after '$' for relative forms like $+5
255+
const QRegularExpression hexTargetRe(QStringLiteral("\\$[+\\-]?[0-9A-Fa-f]+\\b"));
256+
QRegularExpressionMatchIterator hIt = hexTargetRe.globalMatch(operands);
257+
while (hIt.hasNext()) {
258+
const auto m2 = hIt.next();
259+
if (m2.hasMatch()) {
260+
const int s = operandStart + m2.capturedStart();
261+
const int l = m2.capturedLength();
262+
setFormat(s, l, controlFlowTargetFormat);
263+
}
264+
}
265+
266+
// equate/label tokens (exclude registers and condition codes)
267+
const QRegularExpression labelRe(QStringLiteral("\\b[._A-Za-z][._A-Za-z0-9]*\\b"));
268+
269+
QRegularExpressionMatchIterator lIt = labelRe.globalMatch(operands);
270+
while (lIt.hasNext()) {
271+
const auto m3 = lIt.next();
272+
if (m3.hasMatch()) {
273+
const QString tok = m3.captured().toUpper();
274+
if (std::any_of(reservedTokens.begin(), reservedTokens.end(),
275+
[&](const QLatin1StringView t){ return tok == t; })) {
276+
continue;
277+
}
278+
const int start = operandStart + m3.capturedStart();
279+
const int len = m3.capturedLength();
280+
setFormat(start, len, controlFlowTargetFormat);
281+
}
282+
}
199283
}
200-
}
284+
}

gui/qt/datawidget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <QtGui/QTextCharFormat>
77
#include <QtCore/QRegularExpression>
88
#include <QtCore/QObject>
9+
#include <QtCore/QStringList>
910

1011
QT_BEGIN_NAMESPACE
1112
class QPaintEvent;
@@ -39,6 +40,8 @@ class AsmHighlighter : public QSyntaxHighlighter
3940
QTextCharFormat breakPFormat;
4041
QTextCharFormat bytesFormat;
4142
QTextCharFormat mnemonicFormat;
43+
QTextCharFormat controlFlowFormat;
44+
QTextCharFormat controlFlowTargetFormat;
4245
QTextCharFormat hexFormat;
4346
QTextCharFormat decimalFormat;
4447
QTextCharFormat parenFormat;

0 commit comments

Comments
 (0)