Ein Set of WideChar hat ein bisschen viele Bitstheo hat geschrieben:In vielen Bereichen hat das Set of Char bei Unicode sowieso ausgedient.

-Michael
Ein Set of WideChar hat ein bisschen viele Bitstheo hat geschrieben:In vielen Bereichen hat das Set of Char bei Unicode sowieso ausgedient.
Code: Alles auswählen
if (s[i] in ['0'..'9']) or
(
((Length(Result) > 0) and (s[i] in ['-', '+']))
and
(
(Result[High(Result)].Wertigkeit in [6, 9, 8])
or
(Result[High(Result)].Wertigkeit = -1)
)
)
then
begin
// Hier kann man leicht nicht erlaubte mathematische Operatorenfolgen auszuschließen: ++ und -+ und ^+
if s[i] = '+' then
raise Exception.Create('[TOKENIZER] -+ oder ++ oder ^+ gefunden. Abbruch.');
// Damit auch Zahlen >9 als EIN Token vorhanden sind, muss der String bei dem ersten Kontakt mit einer Zahl näher untersucht werden
Tmp := ScanNumber(s, i);
AddArray(Tmp, 0);
inc(i, Length(Tmp));
end else
if s[i] in ['a'..'z', 'A'..'Z'] then
begin
// Buchstaben weisen eindeutig auf Funktionen hin.
ka := -1;
ke := -1;
j := i;
// Da eine Funktion einen Parameter besitzt, welcher in Klammern steht, müssen die Positionen der Klammern im String bestimmt werden.
while (j < Length(s)) do
begin
if s[Succ(j)] = '(' then
ka := Succ(j)
else
if s[Succ(j)] = ')' then
begin
ke := Succ(j);
Break;
end;
inc(j);
end;
if (ka <> -1) and (ke <> -1) then
begin
// Sind beide Klammern gefunden worden, muss man...
// ...die öffnende Klammer als Token hinzufügen
AddArray('(', -1);
// ...den Funktionsterm als Tokens hinzufügen
Result := TokenizeInfix(Copy(s, Succ(ka), Pred(ke-ka)));
// ...die schließende Klammer als Token hinzufügen
AddArray(')', -2);
AddArray(Copy(s, i, ka-i), 10);
end else
// Ist kein Parameter vorhanden, handelt es sich um keine Funktion. Abbruch.
raise Exception.Create('[TOKENIZER] Funktion enthält keinen Parameter. Abbruch.');
i := Succ(ke);
end else
// Operatoren
// Fakultäten und DegToRad ähneln von der endgültigen Abarbeitung her der Potenz
if s[i] in ['^', '!', '°'] then
begin
AddArray(s[i], 9); // Potenz vor...
inc(i, Length(s[i]));
end else
if s[i] in ['*', '/', '%'] then
begin
AddArray(s[i], 8); // Punkt vor...
inc(i, Length(s[i]));
end else
if s[i] in ['+', '-'] then
begin
AddArray(s[i], 6); // Strich vor...
inc(i, Length(s[i]));
end else
if s[i] = '(' then
begin
AddArray(s[i], -1); // Klammer auf.
inc(i, Length(s[i]));
end else
if s[i] = ')' then
begin
AddArray(s[i], -2); // Die Wertigkeit ist nur -2, da die Wertigkeit an sich unbedeutend und somit regelrecht am niedrigsten ist
inc(i, Length(s[i]));
end else
// Leerzeichen werden ignoriert
if s[i] = ' ' then
inc(i)
else
// Im Falle eines unbekannten Zeichens, ist die Weiterzerlegung unmöglich.
raise Exception.Create('[TOKENIZER] Token "'+s[i]+'" unbekannt. Abbruch.');
Code: Alles auswählen
var Tokens: TDynTokenArray;
begin
Tokens := TokenizeInfix(UTF8Decode(e.Text));
end;
function TfrmMain.TokenizeInfix(s : WideString) : TDynTokenArray;
procedure AddArray(aInhalt : WideString; aWertigkeit : Integer);
begin
SetLength(Result, Succ(Length(Result)));
with Result[High(Result)] do
begin
Inhalt := aInhalt;
Wertigkeit := aWertigkeit;
end;
end;
var i : Integer;
begin
i := 1;
while i <= Length(s) do
begin
if s[i] in ['^', '!', #$B0] then
begin
AddArray(s[i], 9);
inc(i, Length(s[i]));
end else
raise Exception.Create('[TOKENIZER] Token "'+s[i]+'" unbekannt. Abbruch.');
end;
end;
Code: Alles auswählen
initialization
widestringmanager.Wide2AnsiMoveProc:=@defaultWide2AnsiMove;
widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2WideMove;
...
Du kannst in Lazarus nicht einfach eine String-Konstante auf einen Widetring zuordnen oder mit einem Widestring vergleichen. In lazarus kommen String-Konstanten als UTF-8 heraus, der FPC-Compiler hält sie aber für ANSI (er hat keinen funktionalen UTF8-Typ) und konvertiert sie dann so (also völlig falsch) in Widestrings. Du musst bei allen Konstanten (und immer wenn Du einen WideString an LCL übergeben oder von der LCL empfangen willst)eine explizite Umwandlungs-Routine Widestring <-> UTF8 aufrufen.Nils hat geschrieben:Ich habe nun den Funktionsparameter zu WideString geändert und prüfe in der Funktion nun auf #$B0, allerdings trifft diese If-Abfrage nie zu. Muss ich noch irgendetwas mit dem String aus dem Edit vorher anstellen ?
Bleibt noch anzumerken, dass der Compiler das schon richtig machen würde, falls er wüsste, dass der Quelltext in utf-8 gespeichert ist, also beispielsweise durch Angabe von -Fcutf8 beim kompilieren. Da Lazarus auf allen Platformen utf-8 codierte ansistrings verwendet, wird diese Vorgehensweise leider verunmöglicht.mschnell hat geschrieben:In lazarus kommen String-Konstanten als UTF-8 heraus, der FPC-Compiler hält sie aber für ANSI (er hat keinen funktionalen UTF8-Typ) und konvertiert sie dann so (also völlig falsch) in Widestrings.