Thema: Delphi Einheiten parsen

Einzelnen Beitrag anzeigen

Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#37

AW: Einheiten parsen

  Alt 13. Mär 2015, 17:32
Irgendwo hier ist auch Code für einen Parser der mit 50 Zeilen Code auskommt.
50 Zeilen ist heftig. Bin bei 120 Zeilen (inkl. unärem Minus). Schönes WE.
Delphi-Quellcode:
unit uSimpleParser; // (C) 2011, Dr. Joachim Mohr, Dipl.-Ing. Thomas Abel;

interface

uses
  SysUtils, StrUtils, Math;

function TermToFloat(S: string): double;

implementation

function OperatorPos(const Substr, S: string): integer;
var
  I, N: integer;
begin
  Result := 0;
  N := 0;
  for I := Length(S) downto 1 do
  begin
    if S[I] = '(then Inc(N);
    if S[I] = ')then Dec(N);
    if N = 0 then
      if PosEx(Substr, S, I) = I then
      begin
        Result := I;
        Break;
      end;
  end;
end;

function StrMid(const S: string; const A, B: integer): string;
begin
  Result := Copy(S, A, B - A + 1)
end;

function StrLeft(const S: string; const B: integer): string;
begin
  Result := StrMid(S, 1, B);
end;

function StrRight(const S: string; const A: integer): string;
begin
  Result := StrMid(S, A, Length(S));
end;

function Left(const S, Substr: string): string;
begin
  Result := StrLeft(S, OperatorPos(Substr, S) - 1);
end;

function Right(const S, Substr: string): string;
begin
  Result := StrRight(S, OperatorPos(Substr, S) + Length(Substr));
end;

function Parenthesis(var S: string; const Minus: boolean): boolean;
begin
  Result := false;
  if Minus then
  begin
    if Length(S) > 3 then
      if Copy(S, 1, 2) = '~(then
      begin
        S := StrMid(S, 3, Length(S) - 1);
        Result := true;
      end;
  end
  else
  begin
    if Length(S) > 2 then
      if S[1] = '(then
      begin
        S := StrMid(S, 2, Length(S) - 1);
        Result := true;
      end;
  end;
end;

function Solve(S: string): double;
begin
  try
    if OperatorPos('+', S) > 0 then
      Result := Solve(Left(S, '+')) + Solve(Right(S, '+'))
    else
      if OperatorPos('-', S) > 0 then
        Result := Solve(Left(S, '-')) - Solve(Right(S, '-'))
      else
        if OperatorPos('*', S) > 0 then
          Result := Solve(Left(S, '*')) * Solve(Right(S, '*'))
        else
          if OperatorPos('/', S) > 0 then
            Result := Solve(Left(S, '/')) / Solve(Right(S, '/'))
          else
            if Parenthesis(S, true) then
              Result := -Solve(S)
            else
              if Parenthesis(S, false) then
                Result := Solve(S)
              else
                Result := StrToFloat(StringReplace(S, '~', '-', []));
  except
    Result := 0;
  end;
end;

function TermToFloat(S: string): double; // ~ für unäres Minus;
begin
  Result := 0;
  S := StringReplace(S, #32, '', [rfReplaceAll]);
  if Length(S) > 0 then
  begin
    if S[1] = '-then S[1] := '~';
    if S[1] = '+then Delete(S, 1, 1);
    S := StringReplace(S, '*+', '*', [rfReplaceAll]);
    S := StringReplace(S, '/+', '/', [rfReplaceAll]);
    S := StringReplace(S, '(+', '(', [rfReplaceAll]);
    S := StringReplace(S, '*-', '*~', [rfReplaceAll]);
    S := StringReplace(S, '/-', '/~', [rfReplaceAll]);
    S := StringReplace(S, '(-', '(~', [rfReplaceAll]);
    Result := Solve(S);
  end;
end;

end.

Geändert von Bjoerk (13. Mär 2015 um 17:47 Uhr) Grund: -Solve(S)
  Mit Zitat antworten Zitat