Einzelnen Beitrag anzeigen

Benutzerbild von Mithrandir
Mithrandir
(CodeLib-Manager)

Registriert seit: 27. Nov 2008
Ort: Delmenhorst
2.379 Beiträge
 
#55

Re: Automaten in Source Code

  Alt 22. Nov 2009, 17:55
Moah... Also, jetzt wurde hier fast 50 Beiträge lang diskutiert, debattiert, rumgeschoben, angemeckert usw. Ich versteh langsam immer weniger. Automaten sind mir bekannt, und ich find sie faszinierend, da man mit ihnen nahezu alle Probleme (= Aufgaben) lösen kann.

Ich habe hier für SmallTune eine Übersetzungsklasse geschrieben. Ich habe ein Dateiformat erstellt, das so aussieht:

Delphi-Quellcode:
// Translation File for SmallTune
// Language: German
// Author: Daniel Gilbert
// Mail: [email]me@smalltune.net[/email]

// Must match Application Minor Version
// e.g. "0.3" will work for SmallTune 0.3.0, SmallTune 0.3.1, SmallTune 0.3.2 and so on, but not SmallTune 0.4.0...
TRANS_FILE_VERSION=0.3;

//Short Description:
//
//The default Format is:
//
//index:'Text';
//
//In case you need a ' in your text (e.g.: isn't), you can write it like this:
//
//0:'This isn\'t a problem';
//
//In case you need a linebreak, this can be done this way:
//
//0:'This is the first line \n this is the next line';
//
// NEVER EVER change the index and the line order. Doing so will result in an error and the language won't be loaded

//Windows XP or NT 4.0 needed!
0:'Windows XP or NT 4.0 needed!';
//[Playing]
1:'[Playing]';
//[Pause]
2:'[Pause]';
Der Parser beachtet die Versionsangabe noch nicht. Ich habe auf die klassische "Case"-Variante zurückgegriffen, die alzaimar überhaupt nicht zusagt.

Wie würde man denn so einen Parser als Tabelle implementieren? Ich versteh an diesem Punkt ehrlich gesagt nur Bahnhof, und eine andere Möglichkeit als "Case" konnte ich mir bislang auch nicht vorstellen. Im Anhang gibt es die komplette Unit, hier den Auszug des Parsers:

Delphi-Quellcode:
function TdgstTranslator.ParseFile(Filename: String): Boolean;
var
  TranslationFile: TextFile;
  i: integer;
  tmp, tmp2: String;
begin
  Result := false;
  (* Initialize *)
  SetLength(fTranslations, 0);
  FileMode := fmOpenRead;
  tmp := '';
  tmp2 := '';
  (* Open File *)
  AssignFile(TranslationFile, FileName);
  try
    (* Reset File *)
    Reset(TranslationFile);
    while not EOF(TranslationFile) do
    begin
      (* Read the next line *)
      ReadLN(TranslationFile, tmp);
      fState := tpsNewLine;
      if Length(tmp) > 0 then
        for I := 1 to Length(tmp) do
          case fState of

            (* New Line Started *)
            tpsNewLine:
              begin
                case tmp[I] of

                  '/':
                  begin
                    (* This line is a comment *)
                    fState := tpsComment;
                    Break;
                  end;

                  else
                  begin
                    (* ReInit tmp2 *)
                    tmp2 := '';
                    tmp2 := tmp[I];
                    fState := tpsIndex;
                  end;
                end;
              end;

            (* Line with comment started, can be ignored *)
            tpsComment:
              begin
                fState := tpsNewLine;
                Break;
              end;

            (* Index found *)
            tpsIndex:
              begin
                case tmp[I] of

                  ':':
                    begin
                      (* Index ended, Text will start *)
                      SetLength(fTranslations, Length(fTranslations) + 1);
                      If not (StrToIntDef(tmp2, 0) = Length(fTranslations) - 1) then
                      begin
                        fState := tpsFailure;
                        Break;
                      end
                      else
                        fState := tpsTextBegin;
                    end;

                  else
                    begin
                      tmp2 := tmp2 + tmp[I];
                    end;
                end;
              end;

            (* New Text Begins *)
            tpsTextBegin:
              begin
                case tmp[I] of
                  '''':
                    begin
                      fState := tpsTextReading;
                      tmp2 := '';
                    end;
                end;
              end;

            (* Beginning was found, reading the current string *)
            tpsTextReading:
              begin
                case tmp[I] of
                  '\': fState := tpsCtrlCommand;
                  '''': fState := tpsTextEnd;
                  else
                    tmp2 := tmp2 + tmp[I];
                end;
              end;

            (* Text has ended *)
            tpsTextEnd:
              begin
                case tmp[i] of
                  ';':
                    begin
                      fTranslations[Length(fTranslations) - 1] := tmp2;
                      fState := tpsNewLine;
                    end;
                end;
              end;

            (* The control character has been found *)
            tpsCtrlCommand:
              begin
                case tmp[i] of
                  'n': tmp2 := tmp2 + #13#10;
                  '''': tmp2 := tmp2 + '''';
                  '\': tmp2 := tmp2 + '\';
                end;
                fState := tpsTextReading;
              end;
      end;
    end;
  finally
    CloseFile(TranslationFile);
  end;
end;
Angehängte Dateien
Dateityp: pas dgsttranslator_205.pas (6,3 KB, 2x aufgerufen)
米斯蘭迪爾
"In einer Zeit universellen Betruges wird das Aussprechen der Wahrheit zu einem revolutionären Akt." -- 1984, George Orwell
  Mit Zitat antworten Zitat