有何没道理,其他的解析器不都是人写出来的。<br>不过你可以不写,网上有几个这样的控件。<br><br><br>{<br><br> TFatExpression by Gasper Kozak, gasper.kozak@email.si<br> component is open-source and is free for any use<br> version: 1.01, July 2001<br><br> this is a component used for calculating text-presented expressions<br> features<br> operations: + - * / ^ !<br> parenthesis: ( )<br> variables: their values are requested through OnEvaluate event<br> user-defined functions in format:<br> function_name [ (argument_name [";" argument_name ... ]] "=" expression<br><br> ! parental advisory : bugs included<br> if you find any, fix it or let me know<br><br>}<br><br>unit FatExpression;<br><br>interface<br><br>uses Classes, Dialogs, Sysutils, Math;<br><br>type<br> // empty token, numeric, (), +-*/^!, function or variable, ";" character<br> TTokenType = (ttNone, ttNumeric, ttParenthesis, ttOperation, ttString, ttParamDelimitor);<br> TEvaluateOrder = (eoInternalFirst, eoEventFirst);<br> TOnEvaluate = procedure(Sender: TObject; Eval: String; Args: array of Double;<br> ArgCount: Integer; var Value: Double; var Done: Boolean) of object;<br><br> // class used by TExpParser and TExpNode for breaking text into <br> // tokens and building a syntax tree<br> TExpToken = class<br> private<br> FText: String;<br> FTokenType: TTokenType;<br> public<br> property Text: String read FText;<br> property TokenType: TTokenType read FTokenType;<br> end;<br><br> // engine for breaking text into tokens<br> TExpParser = class<br> protected<br> FExpression: String;<br> FTokens: TList;<br> FPos: Integer;<br> private<br> procedure Clear;<br> function GetToken(Index: Integer): TExpToken;<br> procedure SetExpression(const Value: String);<br> public<br> constructor Create;<br> destructor Destroy; override;<br><br> function ReadFirstToken: TExpToken;<br> function ReadNextToken: TExpToken;<br><br> function TokenCount: Integer;<br> property Tokens[Index: Integer]: TExpToken read GetToken;<br> property TokenList: TList read FTokens;<br> property Expression: String read FExpression write SetExpression;<br> end;<br><br> // syntax-tree node. this engine uses a bit upgraded binary-tree<br> TExpNode = class<br> protected<br> FOwner: TObject;<br> FParent: TExpNode;<br> FChildren: TList;<br> FTokens: TList;<br> FLevel: Integer;<br> FToken: TExpToken;<br> FOnEvaluate: TOnEvaluate;<br> private<br> function GetToken(Index: Integer): TExpToken;<br> function GetChildren(Index: Integer): TExpNode;<br> function FindLSOTI: Integer; // LSOTI = least significant operation token index<br> function ParseFunction: Boolean;<br> procedure RemoveSorroundingParenthesis;<br> procedure SplitToChildren(TokenIndex: Integer);<br> function Evaluate: Double;<br> property Children[Index: Integer]: TExpNode read GetChildren;<br> public<br> constructor Create(AOwner: TObject; AParent: TExpNode; Tokens: TList);<br> destructor Destroy; override;<br> procedure Build;<br><br> function TokenCount: Integer;<br> function Calculate: Double;<br> property Tokens[Index: Integer]: TExpToken read GetToken;<br> property Parent: TExpNode read FParent;<br> property Level: Integer read FLevel;<br> property OnEvaluate: TOnEvaluate read FOnEvaluate write FOnEvaluate;<br> end;<br><br> TFunction = class<br> protected<br> FAsString, FName, FHead, FFunction: String;<br> FOwner: TObject;<br> FArgCount: Integer;<br> FArgs: TStringList;<br> FValues: array of Double;<br> private<br> procedure SetAsString(const Value: String);<br> procedure EvalArgs(Sender: TObject; Eval: String; Args: array of Double; ArgCount: Integer; var Value: Double);<br> public<br> constructor Create(AOwner: TObject);<br> destructor Destroy; override;<br> function Call(Values: array of Double): Double;<br> property AsString: String read FAsString write SetAsString;<br> property Name: String read FName;<br> property ArgCount: Integer read FArgCount;<br> property Args: TStringList read FArgs;<br> end;<br><br> // main component, actually only a wrapper for TExpParser, TExpNode and<br> // user input via OnEvaluate event<br> TFatExpression = class(TComponent)<br> protected<br> FInfo, FText: String;<br> FEvaluateOrder: TEvaluateOrder;<br> FOnEvaluate: TOnEvaluate;<br> FValue: Double;<br> FFunctions: TStringList;<br> private<br> procedure Compile;<br> function GetValue: Double;<br> procedure SetInfo(Value: String);<br> procedure Evaluate(Eval: String; Args: array of Double; var Value: Double);<br> function FindFunction(FuncName: String): TFunction;<br> procedure SetFunctions(Value: TStringList);<br> public<br> constructor Create(AOwner: TComponent); override;<br> destructor Destroy; override;<br> property Value: Double read GetValue;<br> published<br> property Text: String read FText write FText;<br> property Info: String read FInfo write SetInfo;<br> property Functions: TStringList read FFunctions write SetFunctions;<br> property EvaluateOrder: TEvaluateOrder read FEvaluateOrder write FEvaluateOrder;<br> property OnEvaluate: TOnEvaluate read FOnEvaluate write FOnEvaluate;<br> end;<br><br><br>procedure Register;<br><br>implementation<br><br>const<br> // supported operations<br> STR_OPERATION = '+-*/^!';<br> // function parameter delimitor<br> STR_PARAMDELIMITOR = ';';<br> // legal variable name characters<br> STR_STRING : array[0..1] of string =<br> ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_',<br> 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$#@0123456789');<br><br><br>procedure Register;<br>begin<br> RegisterComponents('Additional', [TFatExpression]);<br>end;<br><br><br><br>function OperParamateres(const Oper: String): Integer;<br>begin<br> if Pos(Oper, '+-*/^') > 0 then<br> Result := 2 else<br> if Oper = '!' then<br> Result := 1 else<br> Result := 0;<br>end;<br><br>constructor TExpParser.Create;<br>begin<br> inherited Create;<br> FTokens := TList.Create;<br>end;<br><br>destructor TExpParser.Destroy;<br>begin<br> Clear;<br> FTokens.Free;<br> inherited;<br>end;<br><br>procedure TExpParser.Clear;<br>begin<br> while FTokens.Count > 0 do begin<br> TExpToken(FTokens[0]).Free;<br> FTokens.Delete(0);<br> end;<br>end;<br><br>procedure TExpParser.SetExpression(const Value: String);<br>begin<br> FExpression := Trim(Value);<br>end;<br><br>function TExpParser.GetToken(Index: Integer): TExpToken;<br>begin<br> Result := TExpToken(FTokens[Index]);<br>end;<br><br>function TExpParser.ReadFirstToken: TExpToken;<br>begin<br> Clear;<br> FPos := 1;<br> Result := ReadNextToken;<br>end;<br><br>function GetTokenType(S: String; First: Boolean): TTokenType;<br>var Value: Double;<br> P, Error: Integer;<br>begin<br> if (S = '(') or (S = ')') then Result := ttParenthesis else<br> if S = STR_PARAMDELIMITOR then Result := ttParamDelimitor else<br> if Pos(S, STR_OPERATION) > 0 then Result := ttOperation else<br> begin<br> Val(S, Value, Error);<br> if Error = 0 then Result := ttNumeric else<br> begin<br> if First then<br> P := Pos(S, STR_STRING[0]) else<br> P := Pos(S, STR_STRING[1]);<br><br> if P > 0 then<br> Result := ttString else<br> Result := ttNone;<br> end;<br> end;<br>end;<br><br>function TExpParser.ReadNextToken: TExpToken;<br>var Part, Ch: String;<br> FirstType, NextType: TTokenType;<br> Sci: Boolean;<br>begin<br> Result := NIL;<br> if FPos > Length(FExpression) then Exit;<br> Sci := False;<br><br> Part := '';<br> repeat<br> Ch := FExpression[FPos];<br> Inc(FPos);<br> until (Ch <> ' ') or (FPos > Length(FExpression));<br> if FPos - 1 > Length(FExpression) then Exit;<br><br> FirstType := GetTokenType(Ch, True);<br> if FirstType = ttNone then begin<br> raise Exception.CreateFmt('Parse error: illegal character "%s" at position %d.', [Ch, FPos - 1]);<br> Exit;<br> end;<br><br> if FirstType in [ttParenthesis, ttOperation] then begin<br> Result := TExpToken.Create;<br> with Result do begin<br> FText := Ch;<br> FTokenType := FirstType;<br> end;<br> FTokens.Add(Result);<br> Exit;<br> end;<br><br> Part := Ch;<br> repeat<br> Ch := FExpression[FPos];<br> NextType := GetTokenType(Ch, False);<br><br> if<br> (NextType = FirstType) or<br> ((FirstType = ttString) and (NextType = ttNumeric)) or<br> ((FirstType = ttNumeric) and (NextType = ttString) and (Ch = 'E') and (Sci = False)) or<br> ((FirstType = ttNumeric) and (NextType = ttOperation) and (Ch = '-') and (Sci = True))<br> then<br> begin<br> Part := Part + Ch;<br> if (FirstType = ttNumeric) and (NextType = ttString) and (Ch = 'E') then<br> Sci := True;<br> end else<br> begin<br> Result := TExpToken.Create;<br> with Result do begin<br> FText := Part;<br> FTokenType := FirstType;<br> end;<br> FTokens.Add(Result);<br> Exit;<br> end;<br> Inc(FPos);<br> until FPos > Length(FExpression);<br><br> Result := TExpToken.Create;<br> with Result do begin<br> FText := Part;<br> FTokenType := FirstType;<br> end;<br> FTokens.Add(Result);<br>end;<br><br>function TExpParser.TokenCount: Integer;<br>begin<br> Result := FTokens.Count;<br>end;<br><br><br><br><br>constructor TExpNode.Create(AOwner: TObject; AParent: TExpNode; Tokens: TList);<br>var I: Integer;<br>begin<br> inherited Create;<br><br> FOwner := AOwner;<br> FParent := AParent;<br> if FParent = NIL then<br> FLevel := 0 else<br> FLevel := FParent.Level + 1;<br><br> FTokens := TList.Create;<br> I := 0;<br> while I < Tokens.Count do begin<br> FTokens.Add(Tokens);<br> Inc(I);<br> end;<br><br> FChildren := TList.Create;<br><br> if Tokens.Count = 1 then<br> FToken := Tokens[0];<br>end;<br><br>destructor TExpNode.Destroy;<br>var Child: TExpNode;<br>begin<br> if Assigned(FChildren) then begin<br> while FChildren.Count > 0 do begin<br> Child := Children[FChildren.Count - 1];<br> FreeAndNil(Child);<br> FChildren.Delete(FChildren.Count - 1);<br> end;<br><br> FreeAndNil(FChildren);<br> end;<br><br> FTokens.Free;<br> inherited;<br>end;<br><br>procedure TExpNode.RemoveSorroundingParenthesis;<br>var First, Last, Lvl, I: Integer;<br> Sorrounding: Boolean;<br>begin<br> First := 0;<br> Last := TokenCount - 1;<br> while Last > First do begin<br> if (Tokens[First].TokenType = ttParenthesis) and (Tokens[Last].TokenType = ttParenthesis) and<br> (Tokens[First].Text = '(') and (Tokens[Last].Text = ')') then begin<br><br> Lvl := 0;<br> I := 0;<br> Sorrounding := True;<br> repeat<br> if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = '(') then<br> Inc(Lvl) else<br> if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = ')') then<br> Dec(Lvl);<br><br> if (Lvl = 0) and (I < TokenCount - 1) then begin<br> Sorrounding := False;<br> Break;<br> end;<br><br> Inc(I);<br> until I = TokenCount;<br><br> if Sorrounding then begin<br> FTokens.Delete(Last);<br> FTokens.Delete(First);<br> end else<br> Exit;<br> end else<br> Exit;<br> <br> First := 0;<br> Last := TokenCount - 1;<br> end;<br>end;<br><br>procedure TExpNode.Build;<br>var LSOTI: Integer;<br>begin<br> if TokenCount < 2 then<br> Exit;<br> RemoveSorroundingParenthesis;<br> if TokenCount < 2 then<br> Exit;<br><br> LSOTI := FindLSOTI;<br> if LSOTI < 0 then begin<br> if ParseFunction then Exit;<br> raise Exception.Create('Compile error: syntax fault.');<br> Exit;<br> end;<br> SplitToChildren(LSOTI);<br>end;<br><br>function TExpNode.ParseFunction: Boolean;<br>var Func: Boolean;<br> I, Delimitor, DelimitorLevel: Integer;<br> FChild: TExpNode;<br> FList: TList;<br>begin<br> Result := False;<br> if TokenCount < 4 then Exit;<br><br> Func := (Tokens[0].TokenType = ttString) and<br> (Tokens[1].TokenType = ttParenthesis) and (Tokens[TokenCount - 1].TokenType = ttParenthesis);<br><br> if not Func then Exit;<br><br> FToken := Tokens[0];<br> with FTokens do begin<br> Delete(TokenCount - 1);<br> Delete(1);<br> end;<br><br> FList := TList.Create;<br> try<br> while TokenCount > 1 do begin<br> Delimitor := - 1;<br> DelimitorLevel := 0;<br> for I := 1 to TokenCount - 1 do begin<br> if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = '(') then<br> Inc(DelimitorLevel) else<br> if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = ')') then<br> Dec(DelimitorLevel) else<br> if (Tokens.TokenType = ttParamDelimitor) and (DelimitorLevel = 0) then begin<br> Delimitor := I - 1;<br> FTokens.Delete(I);<br> Break;<br> end;<br><br> if DelimitorLevel < 0 then begin<br> raise Exception.Create('Function parse error.');<br> Exit;<br> end;<br> end;<br><br> if Delimitor = -1 then Delimitor := TokenCount - 1;<br> for I := 1 to Delimitor do begin<br> FList.Add(Tokens[1]);<br> FTokens.Delete(1);<br> end;<br> FChild := TExpNode.Create(FOwner, Self, FList);<br> FList.Clear;<br> FChild.Build;<br> FChildren.Add(FChild);<br> end;<br> finally<br> FList.Free;<br> end;<br> Result := True;<br>end;<br><br>procedure TExpNode.SplitToChildren(TokenIndex: Integer);<br>var Left, Right: TList;<br> I: Integer;<br> FChild: TExpNode;<br>begin<br> Left := TList.Create;<br> Right := TList.Create;<br><br> try<br> if TokenIndex < TokenCount - 1 then<br> for I := TokenCount - 1 downto TokenIndex + 1 do begin<br> Right.Insert(0, FTokens);<br> FTokens.Delete(I);<br> end;<br><br> if Right.Count > 0 then<br> begin<br> FChild := TExpNode.Create(FOwner, Self, Right);<br> FChildren.Insert(0, FChild);<br> FChild.Build;<br> end;<br><br> if TokenIndex > 0 then<br> for I := TokenIndex - 1 downto 0 do begin<br> Left.Insert(0, FTokens);<br> FTokens.Delete(I);<br> end;<br><br> FChild := TExpNode.Create(FOwner, Self, Left);<br> FChildren.Insert(0, FChild);<br> FChild.Build;<br> finally<br> FToken := Tokens[0];<br> Left.Free;<br> Right.Free;<br> end;<br>end;<br><br>function TExpNode.GetChildren(Index: Integer): TExpNode;<br>begin<br> Result := TExpNode(FChildren[Index]);<br>end;<br><br>function TExpNode.FindLSOTI: Integer;<br>var Lvl, I, LSOTI, NewOperPriority, OperPriority: Integer;<br>begin<br> Lvl := 0; // Lvl = parenthesis level<br> I := 0;<br> LSOTI := - 1;<br> OperPriority := 9;<br><br> repeat<br> if Tokens.TokenType = ttParenthesis then begin<br> if Tokens.Text = '(' then<br> Inc(Lvl) else<br> if Tokens.Text = ')' then<br> Dec(Lvl);<br><br> if Lvl < 0 then begin<br> //raise Exception.CreateFmt('Parenthesis mismatch at level %d, token %d.', [Level, I]);<br> raise Exception.Create('Compile error: parenthesis mismatch.');<br> Exit;<br> end;<br> end;<br><br> if (Tokens.TokenType = ttOperation) and (Lvl = 0) then begin<br> NewOperPriority := Pos(Tokens.Text, STR_OPERATION);<br> if NewOperPriority <= OperPriority then begin<br> OperPriority := NewOperPriority;<br> LSOTI := I;<br> end;<br> end;<br><br> Inc(I);<br> until I >= TokenCount;<br><br> Result := LSOTI;<br>end;<br><br>function Exl(Value: Integer): Double;<br>begin<br> if Value <= 1 then<br> Result := Value else<br> Result := Value * Exl(Value - 1);<br>end;<br><br>function TExpNode.Evaluate: Double;<br>var Args: array of Double;<br> Count, I: Integer;<br> Done: Boolean;<br>begin<br> Result := 0;<br> if FToken.TokenType = ttString then begin<br> Count := FChildren.Count;<br> SetLength(Args, Count);<br> for I := 0 to Count - 1 do<br> Args := Children.Calculate;<br><br> if Assigned(FOnEvaluate) then<br> FOnEvaluate(Self, FToken.Text, Args, High(Args) + 1, Result, Done) else<br> if FOwner is TFatExpression then<br> TFatExpression(FOwner).Evaluate(FToken.Text, Args, Result) else<br> if FOwner is TFunction then<br> TFunction(FOwner).EvalArgs(Self, FToken.Text, Args, High(Args) + 1, Result);<br> end;<br>end;<br><br>function TExpNode.Calculate: Double;<br>var Error: Integer;<br> DivX, DivY: Double;<br>begin<br> Result := 0;<br> if (FToken = NIL) or (TokenCount = 0) then<br> Exit;<br><br> if TokenCount = 1 then begin<br> if FToken.TokenType = ttNumeric then begin<br> Val(FToken.Text, Result, Error);<br> end else<br> if FToken.TokenType = ttString then begin<br> Result := Evaluate;<br> end else<br> if FToken.TokenType = ttOperation then begin<br> if FChildren.Count <> OperParamateres(FToken.Text) then begin<br> raise Exception.Create('Calculate error: syntax tree fault.');<br> Exit;<br> end;<br> if FToken.Text = '+' then<br> Result := Children[0].Calculate + Children[1].Calculate else<br> if FToken.Text = '-' then<br> Result := Children[0].Calculate - Children[1].Calculate else<br> if FToken.Text = '*' then<br> Result := Children[0].Calculate * Children[1].Calculate else<br> if FToken.Text = '/' then begin<br> DivX := Children[0].Calculate;<br> DivY := Children[1].Calculate;<br> if DivY <> 0 then Result := DivX / DivY else<br> begin<br> raise Exception.CreateFmt('Calculate error: "%f / %f" divison by zero.', [DivX, DivY]);<br> Exit;<br> end;<br> end else<br> if FToken.Text = '^' then<br> Result := Power(Children[0].Calculate, Children[1].Calculate) else<br> if FToken.Text = '!' then<br> Result := Exl(Round(Children[0].Calculate));<br> end;<br> end;<br>end;<br><br>function TExpNode.GetToken(Index: Integer): TExpToken;<br>begin<br> Result := TExpToken(FTokens[Index]);<br>end;<br><br>function TExpNode.TokenCount: Integer;<br>begin<br> Result := FTokens.Count;<br>end;<br><br><br><br><br><br><br><br><br>constructor TFunction.Create(AOwner: TObject);<br>begin<br> inherited Create;<br> FOwner := AOwner;<br> FAsString := '';<br> FName := '';<br> FArgCount := 0;<br> FArgs := TStringList.Create;<br>end;<br><br>destructor TFunction.Destroy;<br>begin<br> FArgs.Free;<br> inherited;<br>end;<br><br>function TFunction.Call(Values: array of Double): Double;<br>var Token: TExpToken;<br> Tree: TExpNode;<br> Parser: TExpParser;<br> I: Integer;<br>begin<br> SetLength(FValues, High(Values) + 1);<br> for I := 0 to High(Values) do<br> FValues := Values;<br> <br> Parser := TExpParser.Create;<br> try<br> Parser.Expression := FFunction;<br> Token := Parser.ReadFirstToken;<br> while Token <> NIL do Token := Parser.ReadNextToken;<br><br> Tree := TExpNode.Create(Self, NIL, Parser.TokenList);<br> try<br> with Tree do begin<br> Build;<br> Result := Calculate;<br> end;<br> finally<br> Tree.Free;<br> end;<br> finally<br> Parser.Free;<br> end;<br>end;<br><br>procedure TFunction.EvalArgs(Sender: TObject; Eval: String; Args: array of Double; ArgCount: Integer; var Value: Double);<br>var I: Integer;<br>begin<br> for I := 0 to FArgs.Count - 1 do<br> if UpperCase(FArgs) = UpperCase(Eval) then begin<br> Value := FValues;<br> Exit;<br> end;<br><br> if FOwner is TFatExpression then<br> TFatExpression(FOwner).Evaluate(Eval, Args, Value);<br>end;<br><br>procedure TFunction.SetAsString(const Value: String);<br>var Head: String;<br> HeadPos: Integer;<br> Parser: TExpParser;<br> Token: TExpToken;<br> ExpectParenthesis, ExpectDelimitor: Boolean;<br>begin<br> FArgs.Clear;<br> FArgCount := 0;<br> FAsString := Value;<br> FHead := '';<br> FFunction := '';<br> FName := '';<br><br> HeadPos := Pos('=', FAsString);<br> if HeadPos = 0 then Exit;<br> Head := Copy(FAsString, 1, HeadPos - 1);<br> FFunction := FAsString;<br> Delete(FFunction, 1, HeadPos);<br> Parser := TExpParser.Create;<br> try<br> Parser.Expression := Head;<br> Token := Parser.ReadFirstToken;<br> if (Token = NIL) or (Token.TokenType <> ttString) then begin<br> raise Exception.CreateFmt('Function "%s" is not valid.', [FAsString]);<br> Exit;<br> end;<br> FName := Token.Text;<br><br> Token := Parser.ReadNextToken;<br> if Token = NIL then Exit;<br> if Token.TokenType = ttParenthesis then begin<br> if Token.Text = '(' then ExpectParenthesis := True else<br> begin<br> raise Exception.CreateFmt('Function header "%s" is not valid.', [Head]);<br> Exit;<br> end;<br> end else<br> ExpectParenthesis := False;<br><br> ExpectDelimitor := False;<br> while Token <> NIL do begin<br> Token := Parser.ReadNextToken;<br> if Token <> NIL then begin<br> if Token.TokenType = ttParenthesis then begin<br> if ExpectParenthesis and (Token.Text = ')') then Exit else<br> begin<br> raise Exception.CreateFmt('Function header "%s" is not valid.', [Head]);<br> Exit;<br> end;<br> end;<br><br> if ExpectDelimitor then begin<br> if (Token.TokenType <> ttParamDelimitor) and (Token.TokenType <> ttParenthesis) then begin<br> raise Exception.Create('Function parse error: delimitor ";" expected between arguments.');<br> Exit;<br> end;<br> ExpectDelimitor := False;<br> Continue;<br> end;<br><br> if Token.TokenType = ttString then begin<br> FArgs.Add(Token.Text);<br> FArgCount := FArgs.Count;<br> ExpectDelimitor := True;<br> end;<br> end;<br> end;<br> if ExpectParenthesis then<br> raise Exception.CreateFmt('Function header "%s" is not valid.', [Head]);<br> finally<br> Parser.Free;<br> end;<br>end;<br><br><br><br><br><br>constructor TFatExpression.Create;<br>begin<br> inherited;<br> FText := '';<br> FInfo := 'TFatExpression v1.0 by gasper.kozak@email.si';<br> FFunctions := TStringList.Create;<br>end;<br><br>destructor TFatExpression.Destroy;<br>begin<br> FFunctions.Free;<br> inherited;<br>end;<br><br>procedure TFatExpression.Compile;<br>var Token: TExpToken;<br> Tree: TExpNode;<br> Parser: TExpParser;<br>begin<br> Parser := TExpParser.Create;<br> try<br> Parser.Expression := FText;<br> Token := Parser.ReadFirstToken;<br> while Token <> NIL do<br> Token := Parser.ReadNextToken;<br><br> Tree := TExpNode.Create(Self, NIL, Parser.TokenList);<br> try<br> with Tree do begin<br> Build;<br> FValue := Calculate;<br> end;<br> finally<br> Tree.Free;<br> end;<br> finally<br> Parser.Free;<br> end;<br>end;<br><br>function TFatExpression.FindFunction(FuncName: String): TFunction;<br>var F: TFunction;<br> I: Integer;<br>begin<br> Result := NIL;<br> for I := 0 to FFunctions.Count - 1 do<br> if Trim(FFunctions) <> '' then begin<br> F := TFunction.Create(Self);<br> F.AsString := FFunctions;<br> if UpperCase(F.Name) = UpperCase(FuncName) then begin<br> Result := F;<br> Exit;<br> end;<br> F.Free;<br> end;<br>end;<br><br>procedure TFatExpression.SetInfo(Value: String);<br>begin<br> //<br>end;<br><br>procedure TFatExpression.Evaluate(Eval: String; Args: array of Double; var Value: Double);<br>var Func: TFunction;<br> Done: Boolean;<br>begin<br> Done := False;<br> if (EvaluateOrder = eoEventFirst) and Assigned(FOnEvaluate) then begin<br> FOnEvaluate(Self, Eval, Args, High(Args) + 1, Value, Done);<br> if Done then Exit;<br> end else<br> Value := 0;<br><br> Func := FindFunction(Eval);<br> if Func <> NIL then begin<br> Value := Func.Call(Args);<br> Func.Free;<br> Exit;<br> end;<br><br> if (EvaluateOrder = eoInternalFirst) and Assigned(FOnEvaluate) then<br> FOnEvaluate(Self, Eval, Args, High(Args) + 1, Value, Done) else<br> Value := 0;<br>end;<br><br>function TFatExpression.GetValue: Double;<br>begin<br> Compile;<br> Result := FValue;<br>end;<br><br>procedure TFatExpression.SetFunctions(Value: TStringList);<br>begin<br> FFunctions.Assign(Value);<br>end;<br><br><br>end.<br><br>这是一个带源码的,但是功能还不行,我试过一下,好象不支持括号的嵌套。<br>可以应付简单的计算。你可以在此基础上修改。<br>