[Regexp] define Befehle aus Quelltext Dateien parsen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #16
    Zitat von fireweasel Beitrag anzeigen
    Ohne Not sollte man sich keine Arbeit machen, die schon andere getan haben ...

    Ein größeres Open-Source-Projekt, das was taugt, benutzt für die Lokalisierung üblicherweise ein weitverbreitetes Standardwerkzeug oder bietet wenigstens ein eigenes an. Hat xtc:modify keines? Das wäre (für mich) ein schlechtes Zeichen. Oder benutzt es das gleiche Lokalisierungsformat wie sein Ursprungsprojekt xt-commerce?
    Meinst Du mit dem Standardtool vielleicht gettext?

    Leider habe ich kein Tool dafür gefunden. Und einfach die Original xtc Sprachdateien nehmen geht auch nicht, da der modify ja diverse Module gleich eingebaut hat, deren Sprachdateien dann fehlen würden. Also werde ich mir wohl die Arbeit machen müssen, um es dann weiter zu geben.

    Kommentar


    • #17
      Hallo,
      es sind ein paar Monate rum und endlich kann ich mich an die Übersetzungstabellen machen. *Uff*

      Ich hatte zuerst den Tokenizer ausprobiert und bin nach einigen Experimenten wieder davon abgekommen. Der Tokenizer parst den String nicht, sondern zerlegt ihn nur in kleinste Teile. Aber er gibt nicht an, wo ein Befehl anfängt und aufhört. Das Filtern nach dem define Befehl war nicht schwer. Aber wo hört er dann auf? Erst vor dem nächsten define Befehl? Dann werden auch andere Codeteile in den define Value eingelesen. Nur Kommentare weglassen ist auch kontraproduktiv, die sollten ja gerade erhalten bleiben um den define Bereich nicht völlig nackt zu lassen. Ein paar Hinweise was, wer, wo und warum geändert hat sollten schon bleiben.

      Sei's drum. Ich habe mich also entschlossen mit den RegExp weiter zu machen. Der Ausdruck von Apo und die Erweiterung von Fireweasel haben schon viel geholfen. Vielen Dank nochmal dafür.

      Mein aktueller Ausdruck sieht so aus:
      PHP-Code:
      ^\s*define[^\(]*\(*[\'\"]([^\'\"]+)[\'\"][^,]*,\s*[\'\"]*(.*)(?=[\'\"]*\s*\)\s*;)\s*(?=[\'\"]*\s*\)\s*;[^\n]*) 
      und besteht aus 3 Haupt-Blöcken (grün eingefärbt):
      ^\s*define[^\[COLOR="green"](]*\(*[\'\"]([^\'\"]+)[/COLOR][\'\"][^,]*,\s*[\'\"]*[COLOR="green"](.*)[/COLOR](?=[\'\"]*\s*\)\s*\s*[COLOR="green"](?=[\'\"]*\s*\)\s*;[^\n]*)[/COLOR]

      Der define Name, der Inhalt mit allem was bis zum '); kommt und alles was noch danach stehen sollte. (Kommentare, ...) Geholfen hat mir eine Seite über RegExp Assertions (Behauptungen -> Der RegExp-Evaluator - RegExp-Tutorial - Assertions ) mit denen ich auf ein PHP Zeilenende hin filtern konnte.

      Mein aktuelles Problem: Ich setze die Parameter /imx ein. Sobald ich auch /s setze wird die ganze Datei bis zum Ende des letzten define Befehl als ein einziger Treffer zurück gegeben. Leider kann ich damit keine Multi-Line Befehle erkennen. Zahlen und Texte mit PHP Funktionen & GLOBALS sind kein Problem. Kann mir da jemand weiter helfen? Ich müsste dem Ausdruck sagen, das er nicht! nach [COLOR="black"]['"]*\s*\)\s*;[/COLOR] suchen darf. Das Ausschließen bekommen ich aber nur mit einzelnen Zeichen hin. [^ ]

      Könnt Ihr mir bitte weiter helfen? Hier kann man sich das Ergebnis live anschauen: http://regexp-evaluator.de/evaluator...12a1/#ergebnis

      Beispieltext:
      PHP-Code:
      define('HEADER_M'
                      
      '<br />BIC/SWIFT: ' MODULE_PAYMENT .
      //        '<br />Sort Code: ' . MODULE_PAYMENT_EUTRANSFER_SORTCODE .
                      
      '<br /><br />Die Ware wird ausgeliefert, wenn der Betrag eingegangen ist.<br />');
      define('HEADER_OUT_OF_STOCK_''Die ' STOCK_OUT_OF_STOCK ' Artikel sind nicht auf Lager.<br />');

      define('HEADER_TOTAL',"Summe");
      define('HEADER_NEWLINE',
              
      'Summe');
      define('HEADER_FLOAT'17.5);
      define('HEADER_INT'895); 
      Davon wird schon alles erkannt, bis auf die erste Multiline Zeile.
      Zuletzt geändert von RossiRat; 18.03.2011, 12:31.

      Kommentar


      • #18
        Das mit dem Tokenizer wäre der richtige Weg gewesen. Mit Regexp geht es zwar auch, aber nicht so einfach wie du denkst. Nimm z. B. mal diesen Code:

        PHP-Code:
        /*
        define("foo", "bar");
        */
        define("foo""baz"); 
        Du würdest beide einlesen. Jetzt könntest du anfangen, solche Kommentare berücksichtigen zu wollen, so dass das nicht mehr passiert. Dann hast du aber plötzlich ein Stück Code das so aussieht:

        Code:
        $blockComment = "[COLOR="RoyalBlue"]/*";
        define("foo", "bar");
        //*/[/COLOR]
        define("foo", "baz");
        Jetzt ignorierst du den blauen Teil, obwohl es kein Kommentar ist. Also wieder nichts gewonnen. Bevor du jetzt überlegst, wie du Strings auch noch berücksichtigen kannst, damit sowas nicht passiert, nimm den Tokenizer!

        Gruß,

        Amica
        [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
        Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
        Super, danke!
        [/COLOR]

        Kommentar


        • #19
          Hast Du da schon eine fertige Funktion oder Klasse auf der ich aufbauen kann? Ansonsten ist das nicht so einfach, zumindest für mch. Ich kann ja mal meinen Tokenizer Code posten. Ist ja nicht das ich es nicht probiert hätte:

          Achtung: Da ist noch mein Debug Code drin! (Echo ...)
          PHP-Code:
          // Dateiinhalt in Tokens umwandeln
          $source file_get_contents(ROOT $lang_data['dir'] . '/' $file_name);
          $tokens token_get_all($source);

          $line_number 0;
          $line_text '';
          $define_status '';
          $define_name '';
          $define_line 0;
          $define_list = array();
          foreach (
          $tokens as $token) {
              if (!
          is_array($token)) {
                  
          // einfaches 1-Zeichen Token
                  
          if ($define_status == 'getvalue') {
                      
          $define_value .= $token;
                  
                  }
                  echo 
          '~' $token;
                  
          $line_text .= $token;
                  continue;
                  
              }
              
              
          // Token Array
              
          list($token_id$token_text) = $token;
              
          $line_text .= $token_text;

              switch (
          $token_id) { 
              case 
          T_COMMENT
              case 
          T_ML_COMMENT:
              case 
          T_DOC_COMMENT
                  
          // Kommentare 
                  
          echo '°' $token_text;
                  break;

              case 
          T_STRING
                  
          // Strings (auch define !)
                  
          if (strtolower($token_text) == 'define') {
                      if (
          $define_name '') {
                          
          $define_list[$define_name] = $define_value;
                      }
                      
                      
          $define_line $token_line;
                      
          $define_status 'getname';
                      
          $define_name '';
                      
          $define_value '';
                  }
                  
                  echo 
          '^' $token_text;
                  break;

              case 
          T_CONSTANT_ENCAPSED_STRING:
                  if (
          $define_status == 'getname') {
                      
          $define_name $token_text;
                      
          $define_status 'getvalue';
                      
                  } elseif (
          $define_status == 'getvalue') {
                      
          $define_value .= $token_text;
                      
                  }
                  echo 
          'Ä' $token_text;
                  break;
              
              case 
          T_WHITESPACE;
                  if (
          $define_status == 'getvalue') {
                      
          $define_value .= $token_text;
                  
                  }
                  echo 
          'Ö' $token_text;
                  break;
                  
              default:
                  
          // alle anderen -> unverändert beibehalten
                  
          echo '#' $token_text;
                  break;
              }
          }

          print_r($define_list);

          die(); 
          Man muss alles selber machen: Nach dem passenden Token suchen und danach alles parsen ob es noch Inhalt oder schon neuer Befehl ist. ($define_status)

          Da in den define Dateien auch normaler Code drin steht und in den define Werten auch Konstanten und Kommentare benutzt werden, ist das ein Höllenjob. Nein danke.

          Wer was hat um PHP zu parsen, dann bitte her damit. Ansonsten bräuchte ich Hilfe beim Feintunig des regExp Ausdruckes.

          Kommentar


          • #20
            Du willst doch nur define Statements einlesen, oder?

            Also warte bis T_STRING mit dem Wert "define", ignoriere T_WHITESPACE bis "(", ignoriere T_WHITESPACE bis T_CONSTANT_ENCAPSED_STRING und speichere dessen Wert, ignoriere T_WHITESPACE bis ",", ignoriere T_WHITESPACE bis zum nächsten anderen Token. Ab jetzt zählst du Klammern und pufferst alle Tokens bis zur ersten schließenden Klammer, zu der du keine geöffnete gezählt hattest. Danach nochmal T_WHITESPACE ignorieren bis das ";" kommt. Fertig.

            Edit: Natürlich musst du überall wo du T_WHITESPACE ignorieren sollst, auch noch T_COMMENT ignorieren. Das hatte ich vergessen zu erwähnen.
            Zuletzt geändert von AmicaNoctis; 18.03.2011, 13:13.
            [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
            Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
            Super, danke!
            [/COLOR]

            Kommentar


            • #21
              Klammern zählen! Die guten alten Programmierkniffe - das Leben kann so einfach sein. Ich habe mein Problem gelöst und mir soeben eine Übersetzungsdatenbank erstellt.

              Vielen vielen Dank für den Super Tipp mit den Klammern!

              Hier ist mein Code:
              PHP-Code:
              // Dateiinhalt in Tokens umwandeln
              $source file_get_contents(ROOT $lang_data['dir'] . '/' $file_name);
              $tokens token_get_all($source);
               
              $define_status '';
              $define_name '';
              $define_value '';
              $define_list = array();
              $open_brackets 0;
              foreach (
              $tokens as $token) {
                  
              // Einfaches 1-Zeichen Token?
                  
              if (!is_array($token)) {
                      
                      
              // Wird auf das Komma zwischen Name und Wert gewartet?
                      
              if ($define_status == 'getcomma') {
                          if (
              $token == ",") {
                              
              $define_status 'getvalue';
                              
              $define_value '';        
                              
              $token '';
                          
                              continue;
                          
                          }
                      
                      }
                      
                      
                      
              // Klammer zählen
                      
              if ($define_status == 'getvalue') {
                          switch (
              $token) {
                          case 
              '(':
                              
              $open_brackets++;                        
                              break;
                              
                          case 
              ')':
                              
              $open_brackets--;
                          
                              if (
              $open_brackets == 0) {
                                  
              $define_list[$define_name] = trim($define_value);
                                  
                                  
              $define_status '';
                                  
              $define_name '';
                                  
              $define_value '';        
                                  
              $token '';
                              
                              }
                              break;                            
                      
                          }
                      
                      }
                      
                      
              $define_value .= $token;

                      continue;
                      
                  }
                  
                  
                  
              // Token Array
                  
              list($token_id$token_text) = $token;

                  switch (
              $token_id) { 
                  case 
              T_STRING
                      
              // Strings (auch define !)
                      
              if ($define_status == '' && strtolower($token_text) == 'define') {
                          
              $define_status 'getname';
                          
              $open_brackets++;

                      } elseif (
              $define_status == 'getvalue') {
                          
              $define_value .= $token_text;
                          
                      }                    
                      break;

                  case 
              T_COMMENT
                  case 
              T_ML_COMMENT:
                  case 
              T_DOC_COMMENT
                      
              // Kommentare 
                      
              if ($define_status == 'getvalue') {
                          
              $define_value .= $token_text;
                          
                      }            
                      break;

                  case 
              T_CONSTANT_ENCAPSED_STRING:
                      if (
              $define_status == 'getname') {
                          
              $define_name $token_text;
                          
              $define_status 'getcomma';
                          
                      } elseif (
              $define_status == 'getvalue') {
                          
              $define_value .= $token_text;
                          
                      }
                      break;
                  
                  case 
              T_WHITESPACE;
                      if (
              $define_status == 'getvalue') {
                          
              $define_value .= $token_text;
                      
                      }
                      break;
                      
                  default:
                      
              // alle anderen -> unverändert beibehalten
                      
              if ($define_status == 'getvalue') {
                          
              $define_value .= $token_text;
                      
                      }                    
                      break;
                      
                  }

              }

              print_r($define_list); 

              Kommentar

              Lädt...
              X