Подсветка вложенных скобок

Есть текст со вложенными скобками текст1(текст2(текст3)), глубина вложенности скобок - произвольная, нужно сделать так (не нашел, как подсветить текст здесь) чтобы текст1 был одного цвета, текст2 с внешними скобками - другого и текст3 с внутренними скобками - третьего цвета. Сделать нужно на PyQt. В сети нашел пример и подправив его, получил подсветку только внешних скобок и то что в них.

class MyHighlighter(QSyntaxHighlighter):
    def __init__(self, parent):
        super().__init__(parent)

        self.regexp_by_format = dict()

        char_format = QTextCharFormat()
        char_format.setFontWeight(QFont.Bold)
        char_format.setForeground(Qt.darkRed)
        self.regexp_by_format[r'\((.*)\)'] = char_format

    def highlightBlock(self, text):
        for regexp, char_format in self.regexp_by_format.items():
            expression = QRegularExpression(regexp)
            it = expression.globalMatch(text)
            while it.hasNext():
                match = it.next()
                self.setFormat(match.capturedStart(), match.capturedLength(), char_format)

if __name__ == '__main__':
    mw = QTextEdit()
    mw.setText("text(text(text(text)))")
    highlighter = MyHighlighter(mw.document())    
    mw.show()

Как сделать, чтобы было, как мне нужно? Спасибо.


Ответы (1 шт):

Автор решения: Евгений

Для 4-й глубины вложенности, класс должен выглядеть следующим образом:

import sys
from PyQt5.Qt import *


class MyHighlighter(QSyntaxHighlighter):
    def __init__(self, parent):
        super().__init__(parent)

        self.regexp_by_format = dict()

        char_format = QTextCharFormat()
        char_format.setFontWeight(QFont.Bold)
        char_format.setForeground(Qt.green)
        self.regexp_by_format[r'\([^()]*\([^()]*\([^()]*\)[^()]*\)[^()]*\)'] = char_format

        char_format = QTextCharFormat()
        char_format.setFontWeight(QFont.Bold)
        char_format.setForeground(Qt.blue)
        self.regexp_by_format[r'\([^()]*\([^()]*\)[^()]*\)'] = char_format

        char_format = QTextCharFormat()
        char_format.setFontWeight(QFont.Bold)
        char_format.setForeground(Qt.red)
        self.regexp_by_format[r'\([^()]*\)'] = char_format

    def highlightBlock(self, text):
        for regexp, char_format in self.regexp_by_format.items():
            expression = QRegularExpression(regexp)
            it = expression.globalMatch(text)
            while it.hasNext():
                match = it.next()
                self.setFormat(match.capturedStart(), match.capturedLength(), char_format)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setFont(QFont("Times", 14, QFont.Bold))
    mw = QTextEdit()
    mw.setText("text(text(text(text)))")
    highlighter = MyHighlighter(mw.document())    
    mw.show()
    sys.exit(app.exec_())

введите сюда описание изображения Если ничего не напутал - должно работать.

Да, есть неточность, несколько скобок одной глубины работают неправильно, надо подправить регулярки:

r'\([^()]*(\([^()]*(\([^()]*\))*[^()]*\))*[^()]*\)'
r'\([^()]*(\([^()]*\))*[^()]*\)'
r'\([^()]*\)'
→ Ссылка