JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=638b5921aa22c718fd3d8e64f19bf863Medaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

[c#] brauche Hilfe bei Parser (Precompiler-Teil)

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 23.08.2003, 21:49    Titel: [c#] brauche Hilfe bei Parser (Precompiler-Teil) Antworten mit Zitat

Hallo, Leute!

Ich Realisiere gerade für einen Interpreter einen Precompiler, mit dem ich neben Dingen wie #include, #define usw. auch Kommentare entfernen will (einzeilige wie mehrzeilige)
Das Entfernen von einzeiligen Kommentaren funktioniert schon (siehe Code) aber für mehrzeilige Kommentarehabe ich noch keine Idee.
Meines Erachtens ist die Lösung für die einzeiligen Kommentare auch noch nicht gerade Perfekt. Sie berücksichtigt zwar alle eventuell auftretenden Fälle, arbeitet aber recht langsam. Ist es vielleicht Möglch, mit Hilfe von RegExpressions die Strings zu verarbeiten, so dass ich auf die umständlichen if/else if/else verzichten kann? Ich habe noch nie selbst mit RegEx gearbeitet.
Die fertige Ausgabe wird vorerst zu Testzwecken nur auf der Konsole ausgegeben und sollte keinerlei Kommentare mehr enthalten. Später werde ich die Ausgabe in einer ArrayList Speichern und weiterverarbeiten (Die Precompilerdirektiven, die weiter unten bereits angedeutet sind)
Code:

    public bool Run() {
      String Line;
      int row=0; // Zeilennummer
      int i=0;   // Positionsindex für Textsuche;
      while(sr.Peek()>0) { // sr ist eine geöffnete Datei (StreamReader)
        Line=sr.ReadLine().Trim();
        row++;
        // Einzeilige Kommentare entfernen wobei auf Strings und Chars geachtet werden muß
        if((i=Line.IndexOf("//"))>=0) {
          if(i==0) // Ist ganze Zeile Kommentar
            continue;
          bool InString=false;
          bool InChar=false;
          char[] c=Line.ToCharArray();
          for(i=0; i<c.GetUpperBound(0)-1; i++) {
            if(!InString&&c[i]=='\'') { // Char startet oder endet
              InChar=!InChar;
            }
            if(InChar&&c[i]=='\\'&&c[i+1]=='\'') { // Ein ' innerhalb eines Char
              i++;
              continue;
            }
            if(InChar&&c[i]=='\\'&&c[i+1]=='\\') { // Ein \ innerhalb eines Char
              i++;
              continue;
            }
            if(!InChar&&c[i]=='"') { // String startet oder endet
              InString=!InString;
            }
            if(InString&&c[i]=='\\'&&c[i+1]=='"') { // Ein " innerhalb eines Strings
              i++;
              continue;
            }
            if(InString&&c[i]=='\\'&&c[i+1]=='\\') { // Ein \ innerhalb eines Strings
              i++;
              continue;
            }
            if(!InString&&!InChar&&c[i]=='/'&&c[i+1]=='/') { // Ab hier ist Rest der Zeile Kommentar
              Line=Line.Substring(0, i-1);
              break;
            }
          }
        }
        //TODO: Mehrzeilige Kommentare entfernen wobei auf Strings geachtet werden muß

        // auf Leerzeile testen
        if(Line=="") // Leerzeile
          continue;
        // auf Precompiler-Anweisung testen
        if(Line.StartsWith("#")) { // Precompiler-Anweisung
          if(Line.StartsWith("#include ")) {
            //TODO: Testen auf gültigen Dateinamen
            continue;
          } else if(Line.StartsWith("#define ")) {
          } else if(Line.StartsWith("#if ")) {
          } else if(Line.StartsWith("#ifdef ")) {
          } else if(Line.StartsWith("#ifndef ")) {
          } else if(Line.StartsWith("#else")) {
          } else if(Line.StartsWith("#endif")) {
          } else if(Line.StartsWith("#undef ")) {
          } else if(Line.StartsWith("#warning ")) {
          } else if(Line.StartsWith("#error ")) {
          } else {
            Console.WriteLine("Ungültige Precompiler-Anweisung in {0}:{1}", Path.Combine(GetPath(), GetFile()), row);
            return false;
          }
        }
        Console.WriteLine("Zeile {0}: {1}", row, Line);
      }
      return true;
    }


Wer kann mir in diesem doch recht speziellem Fall helfen?
Eine "RegExLösung" die die Kommentare einfach "Wegzaubert" und dabei auch noch beachtet, daß auch Innerhalb von Strings oder Chars // oder /* vorkommen dürfen wäre mir am liebsten, aber wie gesagt, ich hab mit RegEx noch nie gearbeitet...
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Christian Rousselle
Site Admin


Alter: 48
Anmeldedatum: 19.07.2002
Beiträge: 1630

Medaillen: Keine

BeitragVerfasst am: 24.08.2003, 00:25    Titel: Antworten mit Zitat

Warum interessierst du dich für char, string usw. wenn du nur #define, #if, #endif und Kommentare rausnehmen willst?

Es ist schon spät, aber ich würde sowas machen:

Code:


char GetNextChar(void); // holt den nächsten character, schmeißt whitespace-Zeichen weg

char c;

while(!feof(f))
{
   c = GetNextChar();   
   if('#' == c)
   {
     c = GetNextChar();
     if('d' == c) parsePPDefine();
     else if('i' == c) parsePPIf();
     else Error();
   }
   else if('/' == c)
    {
      c = GetNextChar();
      if('/' == c) ReadComment(); // bis zum nächsten Zeilenumbruch alles überlesen
      else if('*' == c) ReadMLComment(); // bis zum nächsten */ alles überlesen
      // else nichts tun, denn es ist Code
    }

}



C.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 24.08.2003, 10:31    Titel: Antworten mit Zitat

Christian Rousselle hat Folgendes geschrieben:
Warum interessierst du dich für char, string usw. wenn du nur #define, #if, #endif und Kommentare rausnehmen willst?

Wenn innerhalb des zu parsenden Quelltextes eine Codezeile wie diese ist:
Code:
String /*+*/="TestString mit // und /* */-Zeichen sowie \"Anführungsstriche\""; //Kommentar bis Ende der Zeile

muß der Parser trotzdem ordendlich Funktionieren.
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Christian Rousselle
Site Admin


Alter: 48
Anmeldedatum: 19.07.2002
Beiträge: 1630

Medaillen: Keine

BeitragVerfasst am: 24.08.2003, 11:05    Titel: Antworten mit Zitat

Okay,

aber dann muss du diese if..else if nur noch um

Code:

else if(c == '"') ReadString();  // String überlesen
else if(c == '\'') ReadChar();   // char überlesen


erweitern. Man könnte aus dem GetNextChar() auch ein GetNextToken() machen, dass dann anstatt einem Zeichen ein Token ließt. D.h. dass die Funktion wenn sie auf Zeichen wie \" merkt dass es ein normales Zeichen ist, bei ", das einen String einleitet dann TOKEN_STARTSTRING zurückgibt. Dann könnte man sowas machen:

Code:

t = GetNextToken();

if(t == TOKEN_STARTSTRING)
{
    while(t != TOKEN_ENDSTRING)
    {
        GetNextToken();
    }
}
else if(t == TOKEN_SL_COMMENT)
{
   // Komplette Zeile überlesen, bis TOKEN_NEWLINE
}
else if(t == TOKEN_ML_COMMENTSTART)
{
    while(t != TOKEN_ML_COMMENTEND)
    {
        GetNextToken();
    }
}


C.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
The Lord of Programming
Living Legend


Alter: 37
Anmeldedatum: 14.03.2003
Beiträge: 3122

Medaillen: Keine

BeitragVerfasst am: 24.08.2003, 11:18    Titel: Antworten mit Zitat

Wenn du auf Mehrzeilige kommentare testen willst, würde ich einfach eine Variable für den "Status" des Zeichens machen.
Z.B. Wenn du ein " ließt, setzt du den Status auf Zizat(d.h. Kommentarzeichen wird ignoriert). Beim zweiten Lesen des " setzt du den Status wieder auf Normal(d.h. Kommentarzeichen wirkt).
Wenn jetzt /* gelesen wird, testest du, ob der Status Normal ist(sonst wird das Kommentarzeichen als Zeichen des Quellcodes interpretiert). Dann setzt du den Status auf Mehrzeilenkommentar. Wenn du nun auf */ triffst, muss der Status auf Mehrzeilenkommentar stehen und der Kommentar ist zu Ende.
_________________
www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console


Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 24.08.2003, 14:19    Titel: Antworten mit Zitat

Eine Funktion wie "GetNextToken" ist eine gute Idee, damit kann ich sicherlich recht gut Arbeiten.
Als Status kann ich ja dann z.B. InString, InChar, SingleKomment, MultiKomment usw. nutzen.
Ewnn die Funktion "GetNextToken" dann auch noch reservierte Wörter, Variablennamen usw. Filtert, komme ich sicherlich schneller zu meinem gewünschtem Ergebnis.
Eine Liste von Regeln, die besagen, welcher Status wann auftreten darf sollte nicht allzuschwer zu erstellen sein.
Ein PAP auf Papier ist in solchen Fällen immer Hilfreich - und den erstell ich jetzt.
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum