Editeur pascal/delphi avec mise en valeur de la syntaxe

Soyez le premier à donner votre avis sur cette source.

Vue 8 945 fois - Téléchargée 940 fois

Description

Ce code est juste un exemple de la façon d'utiliser le package SyntaxHighlight que j'avais déjà posté ici:
http://www.delphifr.com/codes/MATH-FOR-DELPHI-MATH-IN-DELPHI-BIBLIOTHEQUE-EDITEUR_37753.aspx

Un extracteur de lexèmes est défini à partir du fichier Pascal.lexer. Il est référencé dans Pascal.ppas et sert à générer une définition de parser dans Pascal.pas. Cette définition de lexèmes est utilisée dans les événements OnTokenizeLineClass et OnTokenizeLine du TSyntaxHighlighter de la fiche principale pour colorier la syntaxe du code tappé.

Je crois que je n'ai pas oublié d'éléments du langage Delphi, à peu près tout y est:
-Keywords (begin, end, etc.. merci de me dire si vous constatez qu'il en manque)
-Symboles (;,:=<> etc...)
-Parenthèses et crochets
-Nombres (entiers, flottants et hexadécimal)
-Chaînes de caractères et caractères (par exemple #13)
-Les 3 formes de commentaires:
//Commentaire de fin de ligne
{Commentaire multi-ligne}
(* Commentaire multi-ligne *)
-Directives de compilation {$WARNINGS OFF}
-Assembleur

Juste une petite chose qui mériterait d'être approfondie: l'assembleur pour l'instant est colorié uniformément. Je ne connais pas assez la syntaxe de l'assembleur Delphi pour faire quelque chose de plus détaillé. Et le lexème associé à un bloc assembleur commence par asm et finit par end, c'est à dire que si quelqu'un utilise le mot "end" dans l'assembleur (par exemple dans un commentaire) alors la coloration syntaxique buggera dans ce cas-là.

Je n'ai pas eu la prétention de faire un éditeur évolué, simplement d'illustrer l'utilisation de mes composants: en finallement peu de lignes de code, on arrive à faire un éditeur fonctionnel.

Le code-source des événements du TSyntaxHighlighter est à peine compliqué car l'éditeur travaille ligne par ligne pour la syntaxe, et certains éléments syntaxiques du langage (commentaires, directives de compilation et assembleur) peuvent s'étendre sur plusieurs lignes, c'est pour cela que l'événement OnTokenizeLineClass est utilisé.

Je crois que j'ai battu le record du source le plus long, avec un code source de plus de 7000 lignes et qui pèse 790Ko, c'est à dire plus que le programme une fois compilé! ;-)

Source / Exemple :


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SyntaxHighlighter, VirtualScrollingWinControl,
  SyntaxHighlightMemo, Math, Pascal, COW_RunTime, StrUtils, ComCtrls,
  TextEditorFooter;

type
  TForm1 = class(TForm)
    SyntaxHighlightMemo1: TSyntaxHighlightMemo;
    SyntaxHighlighter1: TSyntaxHighlighter;
    TextEditorFooter1: TTextEditorFooter;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SyntaxHighlighter1TokenizeLineClass(Sender: TObject;
      const LastLineClass: Byte; var NewLineClass: Byte;
      const TextBuffer: PAnsiChar; const TextLength: Integer);
    procedure SyntaxHighlighter1TokenizeLine(Sender: TObject;
      const LineClass: Byte; const TextBuffer: PAnsiChar;
      const TextLength: Integer; CharClass: PCharClassArray);
  private
    FPascalLexer:TDefaultLexer;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FPascalLexer:=TDefaultLexer.Create(PascalLexerDefinition);  
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FPascalLexer.Destroy;  
end;

procedure TForm1.SyntaxHighlighter1TokenizeLineClass(Sender: TObject;  
  const LastLineClass: Byte; var NewLineClass: Byte;                   
  const TextBuffer: PAnsiChar; const TextLength: Integer);             
var                                                                    
  i:ICharBuffer;                                                       
  a:Integer;
begin
  NewLineClass:=LastLineClass;
  if TextLength=0 then
    Exit;
  i:=TDefaultCharBuffer.Create(TextBuffer+#13);
  FPascalLexer.Init(i);      
  repeat                                      
    case NewLineClass of                      
      0:case FPascalLexer.GetNewLexem of      
        3:NewLineClass:=1;                    
        11:NewLineClass:=2;                   
        12:NewLineClass:=3;                   
        13:NewLineClass:=4;                   
      end;
      1:begin                                                       
        a:=PosEx('end',TextBuffer,FPascalLexer.GetLastLexerPos);    
        if a=0 then                                                 
          Break;
        NewLineClass:=0;                                            
        FPascalLexer.SetLastLexerPos(a+3);
      end;
      2,3:begin                                                     
        a:=PosEx('}',TextBuffer,FPascalLexer.GetLastLexerPos);      
        if a=0 then                                                 
          Break;
        NewLineClass:=0;
        FPascalLexer.SetLastLexerPos(a+1);
      end;
      4:begin                                                       
        a:=PosEx('*)',TextBuffer,FPascalLexer.GetLastLexerPos);     
        if a=0 then                                                 
          Break;
        NewLineClass:=0;
        FPascalLexer.SetLastLexerPos(a+2);
      end;
    end;
  until FPascalLexer.GetLexerPos>Cardinal(TextLength);
  i:=nil;                                                           
end;

procedure TForm1.SyntaxHighlighter1TokenizeLine(Sender: TObject;    
  const LineClass: Byte; const TextBuffer: PAnsiChar;               
  const TextLength: Integer; CharClass: PCharClassArray);           
var
  i:ICharBuffer;
  c,l:Byte;
  a:Integer;
begin
  if TextLength=0 then
    Exit;
  i:=TDefaultCharBuffer.Create(TextBuffer+#13);
  FPascalLexer.Init(i);                                             
  l:=LineClass;
  repeat                                      
    case l of                                 
      0:begin                                 
        c:=FPascalLexer.GetNewLexem+1;
        case c of                             
          4:l:=1;                             
          12:begin
            l:=2;                             
            c:=10;                            
          end;
          13:begin
            l:=3;                             
            c:=11;                            
          end;
          14:begin
            l:=4;                             
            c:=11;                            
          end;
          17:c:=0;                            
        end;
        a:=FPascalLexer.GetLexerPos-FPascalLexer.GetLastLexerPos;
        FillChar(CharClass[FPascalLexer.GetLastLexerPos-1],Min(a,TextLength-Integer(FPascalLexer.GetLastLexerPos)+1),c);
      end;                                                                                                               
      1:begin                                                     
        a:=PosEx('end',TextBuffer,FPascalLexer.GetLastLexerPos);  
        if a=0 then
          a:=TextLength;                                          
        FillChar(CharClass[FPascalLexer.GetLastLexerPos-1],
                 Min(a-Integer(FPascalLexer.GetLastLexerPos)+4,TextLength-Integer(FPascalLexer.GetLastLexerPos)+1),4);
        FPascalLexer.SetLastLexerPos(a+3);
        l:=0;
      end;
      2:begin
        a:=PosEx('}',TextBuffer,FPascalLexer.GetLastLexerPos);
        if a=0 then
          a:=TextLength;
        FillChar(CharClass[FPascalLexer.GetLastLexerPos-1],
                 Min(a-Integer(FPascalLexer.GetLastLexerPos)+2,TextLength-Integer(FPascalLexer.GetLastLexerPos)+1),10);
        FPascalLexer.SetLastLexerPos(a+1);
        l:=0;
      end;
      3:begin
        a:=PosEx('}',TextBuffer,FPascalLexer.GetLastLexerPos);
        if a=0 then
          a:=TextLength;
        FillChar(CharClass[FPascalLexer.GetLastLexerPos-1],
                 Min(a-Integer(FPascalLexer.GetLastLexerPos)+2,TextLength-Integer(FPascalLexer.GetLastLexerPos)+1),11);
        FPascalLexer.SetLastLexerPos(a+1);
        l:=0;
      end;
      4:begin
        a:=PosEx('*)',TextBuffer,FPascalLexer.GetLastLexerPos);
        if a=0 then
          a:=TextLength;
        FillChar(CharClass[FPascalLexer.GetLastLexerPos-1],
                 Min(a-Integer(FPascalLexer.GetLastLexerPos)+3,TextLength-Integer(FPascalLexer.GetLastLexerPos)+1),11);
        FPascalLexer.SetLastLexerPos(a+2);
        l:=0;
      end;
    end;
  until FPascalLexer.GetLexerPos>Cardinal(TextLength);
  i:=nil;
end;

end.

Conclusion :


Je ne vois pas trop de catégorie adaptée pour ce code, je le mets donc dans "divers"

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
Merci pour tes remarques fOxi. J'ai enlevé "asm" de la liste des KeyWords car il définit un autre lexème (l'assembleur inline). Il y a plein de mots-clefs que je ne connaissais pas en tout cas: resourcestring ou encore automated.

J'ai aussi enlevé les commentaires du source sur la page, tout de suite ça devient plus lisible...
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
38
a par contre, essaye de refaire la mise en page de cette source et aussi le screen shoot.
tout le monde n'est pas en 1280x1024 ou au dela ...
essaye de faire des screenshoot en 1024x768 ou en dessous... 800x600 c'est deja pas mal...

sinon, c'est du bon boulot, ton travail est vraiment interressant.
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
38
107 au lieu de 93 ...

%KEYWORDS=
@"absolute" | @"abstract" | @"and" | @"array" | @"as" | @"asm" | @"at" | @"automated"
| @"begin"| @"break"
| @"case" | @"cdecl" | @"class" | @"const" | @"constructor" | @"contains"
| @"continue"
| @"default" | @"deprecated" | @"destructor" | @"dispinterface" | @"div" | @"do" | @"downto" | @"dynamic"
| @"else" | @"end" | @"except" | @"exit" | @"export" | @"exports" | @"external"
| @"far" | @"file" | @"finalization" | @"finally" | @"for" | @"forward" | @"function"
| @"goto"
| @"if" | @"implement" | @"implementation" | @"implements" | @"in" | @"index" | @"inherited" | @"initialization" | @"inline" | @"interface" | @"is"
| @"label" | @"library" | @"local"
| @"message" | @"mod" | @"name"
| @"near" | @"nil" | @"not"
| @"object" | @"of" | @"on" | @"or" | @"out" | @"overload" | @"override"
| @"package" | @"packed" | @"pascal" | @"platform" | @"private" | @"procedure" | @"program" | @"property" | @"protected" | @"public" | @"published"
| @"raise" | @"read" | @"record" | @"register" | @"reintroduce" | @"repeat" | @"requires" | @"resourcestring"
| @"safecall" | @"set" | @"shl" | @"shr" | @"stdcall" | @"stored" | @"string"
| @"then" | @"threadvar" | @"to" | @"try" | @"type"
| @"unit" | @"until" | @"uses"
| @"var" | @"virtual"
| @"while" | @"with" | @"write"
| @"xor"


en tout cas ça a l'air costaud comme truc.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.