Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Parsen von Source Code Files (https://www.delphipraxis.net/210181-parsen-von-source-code-files.html)

bernhard_LA 14. Mär 2022 13:27

Parsen von Source Code Files
 
ich muss Sourcecode files für eine Weiterverarbeitung parsen, bzw. umformatieren und hierbei 2 Anforderungen erfüllen :
  1. jeder Befehl wird durch ein ';' abgeschlossen, der Befehl kann über eine beliebige Anzahl von Textzeilen aufgeteilt sein, schreibe den Befehl in eine Zeile = Item einer Stringlsite
  2. behalte Kommentare in der ursprünglichen Formatierung bei, es gibt einzeilige und mehrzeilige Kommentare


hier meine aktuelle noch nicht fertige Lösung:


Delphi-Quellcode:
procedure CopyCommentLines(StartStr, StopStr: string; FileStr: string;
var ReadPos: Integer; FormatedFile: TStringlist);
begin

    if ( i < Length(FileStr)- 2 ) then
     begin


     end;

end;

procedure LoadasFormatedNetlistFile(Filename: String; netlist: TStringlist;
SeparatorChar: Char);
var
  tempstr: String;
  oneline: String;
  tempChar: Char;
  i: Integer;
begin

  ///
  /// read a complete file as TStringlist and assign .text as function result here
  ///
  tempstr := LoadStringFromFile(Filename);

  oneline := '';
  i := 0;

  repeat

    ///
    /// direct copy all comment lines to the clean file
    ///

    CopyCommentLines('/*', '*/', tempstr, i, netlist);

    CopyCommentLines('//', #13#10, tempstr, i, netlist);

    ///
    /// copy all chars until separator into one line
    ///
    tempChar := tempstr[i];

    if (tempChar <> #10) and (tempChar <> #13) then
    begin
      if tempChar <> SeparatorChar then
        oneline := oneline + tempChar
      else
      begin
        oneline := oneline + tempChar;
        netlist.Add(oneline);
        oneline := '';
      end;

    end;

    inc(i);

  until (i >= Length(tempstr));


end;

Frage :

a) gibt es für diese Aufgabe eine einfachere Lösungsmethode
b) in Delphi gibt es keine fertige Methode für das Ausscheniden eines Strings mit start und stop Suchstring ?

Sinspin 14. Mär 2022 14:13

AW: Parsen von Source Code Files
 
Hey,

a) Was ginge, wäre eine TStringList zu verwenden. Wenn du CommaText verwendest und den Delimiter auf Semikolon stellst, sollte dann jede Zeile in der Liste ein Befehl sein, egal über wieviele Zeilen er geht.
Einlesen von MT940 zum Beispiel ;-)

b) Du könntest mit
Delphi-Quellcode:
Copy
arbeiten. Anfang und Anzahl der Zeichen musst du dann halt vorneweg via
Delphi-Quellcode:
Pos
und
Delphi-Quellcode:
PosEx
ermitteln und berechnen.

freimatz 14. Mär 2022 14:26

AW: Parsen von Source Code Files
 
a) Sourcecode in welcher Sprache? Hast Du eine Grammatik dazu? Was ist ein Befehl?
Spielt in der Ausgabe die Reihenfolge der Befehl und Kommentare eine Rolle?

b) eine fertige Methode für das Ausschneiden eines Strings mit start und stop Suchstring ist mir nicht bekannt.

Uwe Raabe 14. Mär 2022 15:13

AW: Parsen von Source Code Files
 
Die Spezifikation ist meiner Meinung nach noch zu vage.

Ist ein ';' immer ein Trennzeichen?

Was passiert, wenn ein Zeilenvorschub entfernt werden muss? Wird er durch ein Leerzeichen ersetzt oder wird die nächste Zeile direkt an die aktuelle angehängt?

Etwas reale Beispiel-Source wäre vielleicht hilfreich.

bernhard_LA 15. Mär 2022 07:39

AW: Parsen von Source Code Files
 
es geht um die Sprache VERILOG , Zusammen mit VHDL wohl die Sprache zur Entwicklung von Mikroelektronik.
Eine kurze Einführung wäre z-B. hier : https://www.iitg.ac.in/hemangee/cs224_2020/verilog2.pdf


Die Beispiele unten sind identische Beschreibungen eine Bauelements


Delphi-Quellcode:
 
sky130_fd_sc_hd__a21oi_1  _25041_ ( .A1(_15472_)
.A2(_16059_)
.B1(_15410_)
.Y(_16230_)
);

 sky130_fd_sc_hd__a21o_1  _25042_ ( .A1(_15433_)
.A2(_15309_)
.B1(_15394_)
.X(_16231_)
);


und

Delphi-Quellcode:
sky130_fd_sc_hd__nor3_1 _29993_ (    .A(_05384_),   .B(_05386_),   .C(_05388_),   .Y(_05389_) );
 
sky130_fd_sc_hd__a211oi_1 _29994_ (    .A1(_05371_),   .A2(_05377_),   .B1(_05382_),   .C1(_05389_),   .Y(_05390_) );
oder


Delphi-Quellcode:
sky130_fd_sc_hd__nor3_1 _29993_ (.A(_05384_), .B(_05386_),.C(_05388_),.Y(_05389_) );
sky130_fd_sc_hd__a211oi_1 _29994_ (.A1(_05371_),.A2(_05377_),.B1(_05382_),.C1(_05389_),.Y(_05390_));

sky130_fd_sc_hd__a211oi_1 _29994_ ( _05371 , _05377_, _05382_, _05389_ , _05390_ );

Gausi 15. Mär 2022 08:26

AW: Parsen von Source Code Files
 
Sind in der originalen Datei auch schon "sinnvolle" Zeilenumbrüche drin, insbesondere nach jedem Semikolon (= Befehlstrenner), oder ist das nur ein langer String ohne solche Steuerzeichen?

Im ersten Fall würde ich die Datei in eine temporäre Stringlist laden. Danach diese Zeile für Zeile durchgehen und dabei die eigentliche Zielliste aufbauen.
  • Wenn einzeiliger Kommentar: Aktuelle Zeile in Zielliste einfügen
  • Beginn eines mehrzeiligen Kommentars: Wechsel in "Kommentarmodus" und Zeile in Zielliste einfügen
  • Im Kommentarmodus: Zeile in Zielliste einfügen, checken auf Kommentar-Ende, ggf. Kommentarmodus verlassen
  • Im Nicht-Kommentarmodus: Zeile an einen temporären String anhängen (ohne Zeilenumbruch). Test auf ";" am Ende, ggf. temporären String in Zielliste einfügen.

Evtl. kann man auch was mit myList.DelimitedText; und ";" als Delimiter machen, aber dann würden Kommentare vermutlich falsch behandelt.

Edit: Ist das richtig, dass in den Aufzählungen (oder: Parameter-Listen) wahlweise ein Komma oder ein Zeilenumbruch gültig ist? Die Kommata müsstest du dann ja ggf. einfügen, wenn du einen mehrzeiligen Befehl in eine Zeile schreibst ...

Sailor 15. Mär 2022 09:44

AW: Parsen von Source Code Files
 
Liste der Anhänge anzeigen (Anzahl: 1)
Im Anhang findest Du eine Grammatik von Verilog, vielleicht hilft's.

Uwe Raabe 15. Mär 2022 09:54

AW: Parsen von Source Code Files
 
Auf den ersten Blick sieht es so aus, als werden lediglich die Zeilenumbrüche durch ", " ersetzt.

KodeZwerg 15. Mär 2022 10:20

AW: Parsen von Source Code Files
 
Habe mal auf die schnelle was getippst wie ich es machen würde. Vielleicht hilft es?!
Delphi-Quellcode:
program FileWriter;

{$APPTYPE CONSOLE}

{.$R *.res}

uses
  System.SysUtils, System.Classes, System.IOUtils;


function MyParse(const AInFile, AOutFile: string): Boolean;
var
  LData: TBytes;
  LOutput: TStringList;
  i: Int64;
  s: string;
begin
  Result := False;
  s := '';
  if FileExists(AInFile) then
    begin
      LOutput := TStringList.Create;
      try
        LData := TFile.ReadAllBytes(AInFile); // Lade Datei in den Speicher
        for i := Low(LData) to High(LData) do
          begin
            if ((LData[i] <> $0D) and (LData[i] <> $0A) and (LData[i] <> $3B) and (LData[i] <> $20)) then // Zeilenumbrüche, Leerzeichen und Semikolon rausfiltern
              s := s + Chr(LData[i]);
            if (LData[i] = $3B) then // Semikolon entdeckt, erstelle fertige Zeile
              begin
                s := s + Chr(LData[i]);
                LOutput.Add(s);
                s := '';
              end;
          end;
        if LOutput.Count > 0 then
          begin
            LOutput.SaveToFile(AOutFile);
            Result := True;
          end;
      finally
        LOutput.Free;
      end;
    end;
end;

var
  LPath: string;
begin
  try
    Writeln('Parser starting...');
    LPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
    MyParse(LPath + 'TestFile.txt', LPath + 'TestOut.txt');
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

//edit

als beispiel InFile:
Delphi-Quellcode:
sky130_fd_sc_hd__a21oi_1 _25041_ ( .A1(_15472_)
.A2(_16059_)
.B1(_15410_)
.Y(_16230_)
);

 sky130_fd_sc_hd__a21o_1 _25042_ ( .A1(_15433_)
.A2(_15309_)
.B1(_15394_)
.X(_16231_)
);sky130_fd_sc_hd__nor3_1 _29993_ ( .A(_05384_), .B(_05386_), .C(_05388_), .Y(_05389_) );
 
sky130_fd_sc_hd__a211oi_1 _29994_ ( .A1(_05371_), .A2(_05377_), .B1(_05382_), .C1(_05389_), .Y(_05390_) );sky130_fd_sc_hd__nor3_1 _29993_ (.A(_05384_), .B(_05386_),.C(_05388_),.Y(_05389_) );
sky130_fd_sc_hd__a211oi_1 _29994_ (.A1(_05371_),.A2(_05377_),.B1(_05382_),.C1(_05389_),.Y(_05390_));

sky130_fd_sc_hd__a211oi_1 _29994_ ( _05371 , _05377_, _05382_, _05389_ , _05390_ );
kommt folgendes raus:
Delphi-Quellcode:
sky130_fd_sc_hd__a21oi_1_25041_(.A1(_15472_).A2(_16059_).B1(_15410_).Y(_16230_));
sky130_fd_sc_hd__a21o_1_25042_(.A1(_15433_).A2(_15309_).B1(_15394_).X(_16231_));
sky130_fd_sc_hd__nor3_1_29993_(.A(_05384_),.B(_05386_),.C(_05388_),.Y(_05389_));
sky130_fd_sc_hd__a211oi_1_29994_(.A1(_05371_),.A2(_05377_),.B1(_05382_),.C1(_05389_),.Y(_05390_));
sky130_fd_sc_hd__nor3_1_29993_(.A(_05384_),.B(_05386_),.C(_05388_),.Y(_05389_));
sky130_fd_sc_hd__a211oi_1_29994_(.A1(_05371_),.A2(_05377_),.B1(_05382_),.C1(_05389_),.Y(_05390_));
sky130_fd_sc_hd__a211oi_1_29994_(_05371,_05377_,_05382_,_05389_,_05390_);


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz