Algorithmus für Syntax Highlighting

Danielku15

Erfahrenes Mitglied
Hi Leute.
Ich stelle mir seit einiger Zeit die Frage was ist die optimale Lösung für ein schnelles SyntaxHighlighting.
Es gibt massig Tutorials im internet jedoch gibt es immer Fehler. Entweder das Syntaxhighlightning wird von Zeile zu Zeile berechnet was mehrzeilige Kommentare und Strings ausschließt.
Oder es wird nur der sichtbare Bereich berechnet was einen Fehler produziert sobald ein Kommentar vor dem sichbaren Bereich beginnt und im Sichtbaren endet.
Oder es ist einfach schlicht sobald der ganze Text geparst wird oder viele Elemente berücksichtigt werden müssen dass das SyntaxHighlightning zu langsam ist.

Es gibt zwar Open Source Programme welche ein reibungsloses SyntaxHighlightning besitzen jedoch sind diese oft im Funktionsumfang so groß dass keiner schlau draus wird wenn ihn nur 1 Element interessiert.

Ich wollte mal euch fragen wie eure Ideen sind. Was ist optimal um ein SyntaxHighlighting zu erstellen? Wie soll man vorgehen? Die Suche und die Formatierung über Regex, RTF oder die eingebauten Such- und Formatierungsfunktionen der TextControls?

gruß Daniel
 
öhm ich schlage vollgendes vor:

du hast ne schleife, die alles durchläuft ...

also zb ... 2bytes zeichen = "*/" <-- nun speicherste die und suchst nach dem "*/"

sobad du das hast, kannst du den text andern färben ;)

ist zwar etwas lahm, aber soll immer functionieren ;) besser wäre es noch mit einem Byte
 
Hi,

Willst du sowas unbedingt selbst schreiben oder brauchst du nur einen Editor mit SyntaxHighlighting?
Wenn das 2, nutzt doch einfach das EditorControl von SciTe
 
Ich will sowas schreiben weil ich nicht vorhabe fertige Komponenten zu verwenden. Diese verpflichten so gut wie immer durch die GPL oder LGPL Lizenz dass das Programm selbst auch wieder unter dieser Lizenz veröffentlicht werden muss. Zudem gehts einfach um das Interesse und die Wissenslust. Da ja viele gute Programmierer hier sind und dieses Thema ja schon sehr oft im Internet erfolglos behandelt wurde könnte man hier mal Aufklärung schaffen
 
Naja, leider scheint keiner so wirklich am Thema interessiert zum sein. Schade auch. Sind ja sehr viele Programmierer hier im Forum unterwegs, da hätte man sicher auf eine optimale Lösung kommen können.
 
Hallo,

ich würde für Syntaxhervorherbung eine Zustandsmaschine (Finite State Machine) implementieren, die auf Grundlage einer Sprachbeschreibung einen Syntaxbaum erstellt, anhand dessen die Hervorhebung vorgenommen wird.

Noch Fragen? ;)

Grüße,
Matthias
 
Ich habe bis jetzt nicht darauf geantwortet weil ich erstmal einbischen drüber sinieren musste. Naja nach langer Überlegunszeit, fände ich es am geschicktesten wenn man erstmal das ganze Dokument ( bei einem bestehenden das geladen wird ) parst und dann während dessen die Colorierung und den Fettdruck sowie Unterstreichungen vornimmt. Ich würde da je nach Programmiersprache Zeilenweise oder Blockweise vorgehen { } etc. Dabei würde ich von innen nach Aussen Parsen und ein Art Block baum aufbauen. Ausserdem würde ich mir überlegen ob ich eine Möglichkeit finde gleiches vorkommen jeweils schnell zu colorieren also quasi ein int gefunden ein int soll rot seín also ersetzte alle int vorkommen von int durch rote ints.
Bei neuen Dokumenten würde ich jeweils nur die Zeilen neu einlesen die der Benutzer gerade Tippt oder ändert, jedesmal das ganze Dokument zu Parsen ist glaube ich zu aufwendig. Ausserdem würde ich mir überlegen zu jedem Dokument den HL Markup zu speichern, sowie das Änderungsdatum, dann könnte man bestehende Dokumente schnell parsen ohne das ein erneutes Parsen nötig wäre.

so nun zerfetzt mich in der Luft :)
 
Matthias Reitinger hat gesagt.:
Hallo,

ich würde für Syntaxhervorherbung eine Zustandsmaschine (Finite State Machine) implementieren, die auf Grundlage einer Sprachbeschreibung einen Syntaxbaum erstellt, anhand dessen die Hervorhebung vorgenommen wird.

Noch Fragen? ;)

Grüße,
Matthias
Hi.
Das Hauptproblem liegt ja dabei das ganze zu Farblich hervorzuheben da dies ja sehr rechenaufwendig ist. Also einen SyntaxBaum habe ich mir Zusammengestellt. Ich habe mir zusammengestellt aus welchen Elementen Quellcodes bestehen. Ich bin zu folgendem Baum gekommen:
XML:
<?xml version="1.0" encoding="utf-8" ?>
<HighlightDoc>
    <MainHighlight def="CSS" />
    <Span start="{" end="}" def="Definition" />    
    
    <HighlightDefs>
        <HighlightDef ID="CSS">
            <Default color="#000000" bgcolor="#FFFFFF" bold="false" italic="false" underline="false" />
            <Variable prefix="." color="#330099" bold="false" italic="false" underline="false" />
            <Range name="Comment" start="/*" end="*/" useescape="false" color="#666666" bold="false" italic="false" underline="false" />
            <Range name="HTMLComment" start="&lt;--" end="--&gt;" useescape="false" color="#666666" bold="false" italic="false" underline="false" />
        </HighlightDef>
        
        <HighlightDef ID="Definition">
            <Range name="String" start='"' end='"' useescape="true" color="#990000" bold="flase" italic="false" underline="false" />
            <Range name="Char" start="'" end="'" useescape="true" color="#990000" bold="flase" italic="false" underline="false" />
            <Variable suffix=":" color="#000099" bold="false" italic="false" underline="false" />
            <Keyword value="bold" color="#009900" bold="false" italic="false" underline="false" />
        </HighlightDef>
    </HighlightDefs>
</HighlightDoc>


Die Klassen in C# sehen so aus:
C#:
    public class HighlightScheme
    {
        private string m_Name = "";
        public string Name
        {
            get
            {
                return m_Name;
            }
            set
            {
                m_Name = value; 
            }
        }

        private HighlightDefinition m_MainHighlight = new HighlightDefinition();
        public HighlightDefinition MainHighlight
        {
            get
            {
                return m_MainHighlight;
            }
            set
            {
                m_MainHighlight = value; 
            }
        }

        private List<HighlightDefinition> m_HighlightDefinitionen = new List<HighlightDefinition>();
        public List<HighlightDefinition> HighlightDefinitionen
        {
            get
            {
                return m_HighlightDefinitionen;
            }
            set
            {
                m_HighlightDefinitionen = value; 
            }
        }
    }

    public class Span
    {
        private string m_Start = "";
        public string Start
        {
            get
            {
                return m_Start;
            }
            set
            {
                m_Start = value; 
            }
        }

        private string m_End = "";
        public string End
        {
            get
            {
                return m_End;
            }
            set
            {
                m_End = value; 
            }
        }

        private string m_HighlightDefName = "";
        public string HighlightDefName
        {
            get
            {
                return m_HighlightDefName;
            }
            set
            {
                m_HighlightDefName = value; 
            }
        }
    }

    public class HighlightDefinition
    {
        private HighlightElement m_Default = new HighlightElement();
        public HighlightElement Default
        {
            get
            {
                return m_Default;
            }
            set
            {
                m_Default = value; 
            }
        }

        private List<Range> m_Ranges = new List<Range>();
        public List<Range> Ranges
        {
            get
            {
                return m_Ranges;
            }
            set
            {
                m_Ranges = value; 
            }
        }

        private List<Variable> m_Variablen = new List<Variable>();
        public List<Variable> Variablen
        {
            get
            {
                return m_Variablen;
            }
            set
            {
                m_Variablen = value; 
            }
        }

        private List<KeyWord> m_KeyWords = new List<KeyWord>();
        public List<KeyWord> KeyWords
        {
            get
            {
                return m_KeyWords;
            }
            set
            {
                m_KeyWords = value; 
            }
        }

        public HighlightDefinition()
        { }
    }

    public class HighlightElement
    {
        private bool m_Bold = false;
        public bool Bold
        {
            get
            {
                return m_Bold;
            }
            set
            {
                m_Bold = value; 
            }
        }

        private bool m_Italic = false;
        public bool Italic
        {
            get
            {
                return m_Italic;
            }
            set
            {
                m_Italic = value; 
            }
        }

        private bool m_Unterline = false;
        public bool Unterline
        {
            get
            {
                return m_Unterline;
            }
            set
            {
                m_Unterline = value; 
            }
        }

        private Color m_ForeColor = Color.Black;
        public Color ForeColor
        {
            get
            {
                return m_ForeColor;
            }
            set
            {
                m_ForeColor = value; 
            }
        }

        public HighlightElement()
        { }
        public HighlightElement(bool bold, bool italic, bool underline, Color forecolor)
        {
            this.Bold = bold;
            this.Italic = italic;
            this.Unterline = underline;
            this.ForeColor = ForeColor;
        }

    }

    public class Range : HighlightElement
    {
        private string m_Start = null;
        public string Start
        {
            get
            {
                return m_Start;
            }
            set
            {
                m_Start = value; 
            }
        }

        private string m_End = null;
        public string End
        {
            get
            {
                return m_End;
            }
            set
            {
                m_End = value; 
            }
        }

        private string m_Name = null;
        public string Name
        {
            get
            {
                return m_Name;
            }
            set
            {
                m_Name = value; 
            }
        }

        private bool m_UseEscape = false;
        public bool UseEscape
        {
            get
            {
                return m_UseEscape;
            }
            set
            {
                m_UseEscape = value; 
            }
        }

        public Range()
        {
            this.Start = "";
            this.End = "";
            this.Name = "";
            this.UseEscape = false;
        }
        public Range(string name, string start, string end, bool useescape, bool bold, bool italic, bool underline, Color forecolor)
        {
            this.Name = name;
            this.Start = start;
            this.End = end;
            this.UseEscape = useescape;
            this.Bold = bold;
            this.Italic = italic;
            this.Unterline = underline;
            this.ForeColor = forecolor;
        }
    }

    public class Variable : HighlightElement
    {
        private string m_Suffix = null;
        public string Suffix
        {
            get
            {
                return m_Suffix;
            }
            set
            {
                m_Suffix = value; 
            }
        }

        private string m_Prefix = null;
        public string Prefix
        {
            get
            {
                return m_Prefix;
            }
            set
            {
                m_Prefix = value; 
            }
        }

        public Variable()
        {
            this.Suffix = "";
            this.Prefix = "";
        }

        public Variable(string suffix, bool bold, bool italic, bool underline, Color forecolor)
        {
            this.Suffix = suffix;
            this.Prefix = "";
            this.Bold = bold;
            this.Italic = italic;
            this.Unterline = underline;
            this.ForeColor = forecolor;
        }

        public Variable(bool bold, string prefix, bool italic, bool underline, Color forecolor)
        {
            this.Suffix = "";
            this.Prefix = prefix;
            this.Bold = bold;
            this.Italic = italic;
            this.Unterline = underline;
            this.ForeColor = forecolor;
        }

        public Variable(string suffix, bool bold, string prefix, bool italic, bool underline, Color forecolor)
        {
            this.Suffix = suffix;
            this.Prefix = prefix;
            this.Bold = bold;
            this.Italic = italic;
            this.Unterline = underline;
            this.ForeColor = forecolor;
        }

    }

    public class KeyWord : HighlightElement
    {
        private string m_Value = null;
        public string Value
        {
            get
            {
                return m_Value;
            }
            set
            {
                m_Value = value; 
            }
        }

        public KeyWord(string value)
        {
            this.Value = value;
        }
        public KeyWord(string value, bool bold, bool italic, bool underline, Color forecolor)
        {
            this.Value = value;
            this.Bold = bold;
            this.Italic = italic;
            this.Unterline = underline;
            this.ForeColor = forecolor;
        }

    }
 
Zuletzt bearbeitet von einem Moderator:
Kurze Frage - warum nicht Reguläre Ausdrücke von C# verwenden? Die können im Prinzip alles was benötigt wird - auch mehrzeilige Kommentare. Eventuell noch eine Präzedenz einführen (Kommentar vor dem Rest prüfen z.B.).
Ich weiss allerdings nicht wie du die Farbe hinbringen willst bzw. wohin.

Ich stell mir das ganze so vor:
Text in einer Art syntaktischen Struktur speichern und diese passend einfärben. Die einzelnen Elemente kann man mit passenden Regexp. rausfischen. Dann noch merken bis zu welcher Stelle im Texteditor man alles geparst hat und wenn etwas dazukommt die Analyse ab dieser Stelle weiter analysieren.
 
Zurück