[gelöst] Syntax Highlighter für PHP mit sehr vielen Keywords

Alles rund um die Programmierung mit Qt
Antworten
B.C.
Beiträge: 15
Registriert: 28. Mai 2011 16:20

[gelöst] Syntax Highlighter für PHP mit sehr vielen Keywords

Beitrag von B.C. »

Hi,

ich bin gerade dabei, neben dem HTML-Highlighter jetzt einen PHP-Highlighter zu schreiben. Dafür habe ich alle php funktionen, konstanten und ähnliches in verschiedene Text-Dateien gepackt, die ich im Quellcode dann gezielt färben möchte. Wenn ich Funktionen + Kontroll Strukuren färben lasse, funktioniert alles wunderbar. Sobald ich allerdings die Konstanten (nochmal 1000+ Wörter) hinzunehme, hängt sich das Programm sofort auf, wenn ich nur eine Eingabe ins Textfeld mache. Wie kann ich das performancegünstiger machen? Hier der jetzige Quellcode

Code: Alles auswählen

#include "phphighlighter.h"

#include <QFile>
#include <QTextStream>

PhpHighlighter::PhpHighlighter(QTextDocument *document) : QSyntaxHighlighter(document)
{
    HighlightingRule rule;

    /*
     * Control Structures like
     * if, else, switch ...
     */
    controlStructuresFormat.setForeground(QColor(161, 161, 0));
    QFile file(":/Keywords/php_control_structures.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;
    QTextStream in(&file);
    while(!in.atEnd()) {
        rule.pattern = QRegExp("\\b" + in.readLine() + "\\b");
        rule.format = controlStructuresFormat;
        highlightingRules.append(rule);
    }

    /*
     * All in PHP predeclared functions
     */
    functionsFormat.setForeground(QColor(100, 74, 155));
    QFile file2(":/Keywords/php_functions.txt");
    if (!file2.open(QIODevice::ReadOnly | QIODevice::Text))
        return;
    QTextStream in2(&file2);
    while(!in2.atEnd()) {
        rule.pattern = QRegExp("\\b" + in2.readLine() + "\\b");
        rule.format = functionsFormat;
        highlightingRules.append(rule);
    }

    constantsFormat.setFontWeight(QFont::Bold);
    QFile file3(":/Keywords/php_constants.txt");
    if (!file3.open(QIODevice::ReadOnly | QIODevice::Text))
        return;
    QTextStream in3(&file3);
    while(!in3.atEnd()) {
        rule.pattern = QRegExp("\\b" + in3.readLine() + "\\b");
        rule.format = constantsFormat;
        highlightingRules.append(rule);
    }
}

void PhpHighlighter::highlightBlock(const QString &text)
{
    foreach (const HighlightingRule &rule, highlightingRules) {
        QRegExp expression(rule.pattern);
        int index = expression.indexIn(text);
        while (index >= 0) {
            int length = expression.matchedLength();
            setFormat(index, length, rule.format);
            index = expression.indexIn(text, index + length);
        }
    }

    setCurrentBlockState(0);
}
Gruß,
Basti
Zuletzt geändert von B.C. am 3. Juni 2011 15:59, insgesamt 1-mal geändert.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Nur ein paar RegEx zusammenbauen und sämtliche Schlüsselwörter in ein QSet packen.
B.C.
Beiträge: 15
Registriert: 28. Mai 2011 16:20

Beitrag von B.C. »

In ein QSet packen ist nicht schwer. Aber wie prüfe ich die jetzt nun alle durch? Wie sieht das am Ende aus?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Bau dir eine RegEx die für alle Keywords gültig ist. Alle Keywords fangen mit einem Buchstaben an, gefolt von x Buchstaben/Zahlen. Wenn diese RegEx matched dann brauchst du blos noch im QSet nachsehen.
B.C.
Beiträge: 15
Registriert: 28. Mai 2011 16:20

Beitrag von B.C. »

Ja gute Idee, ich setz mich denn mal dran
B.C.
Beiträge: 15
Registriert: 28. Mai 2011 16:20

Beitrag von B.C. »

Der reguläre Ausdruck findet immer nur das erste Vorkommen in der Zeile, Ergebnis sieht dann so aus:

Bild

Hier der Code dazu:

Code: Alles auswählen

void PhpHighlighter::highlightBlock(const QString &text)
{
    QRegExp expression("\\b[a-z]+\\b");
    int index = expression.indexIn(text);
    int i = 0;
    while(index >= 0)
    {
        int length = expression.matchedLength();

        if(controlStructures.contains(expression.cap(i)))
            setFormat(index, length, controlStructuresFormat);

        index = expression.indexIn(text, index + length);
        ++i;
    }

    setCurrentBlockState(0);
}
controlStructures ist ein QSet, das Wörter wie if, else, endif usw. enthält.
Was stimmt da mit dem regulären Ausdruck nicht? Ich habs online getestet und da ging alles bestens ...
B.C.
Beiträge: 15
Registriert: 28. Mai 2011 16:20

Beitrag von B.C. »

Ich hab mir mal die Doku von QRegExp::cap() genauer angeschaut und da liegt der Fehler. Ich muss immer cap(0) benutzen, um an das Wort zu kommen. Den Integer i kann ich damit weglassen.
Antworten