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;