如何直接得到文本输入的数学计算公式的值?(200分)

  • 主题发起人 主题发起人 pqx
  • 开始时间 开始时间
P

pqx

Unregistered / Unconfirmed
GUEST, unregistred user!
比如我在文本控件中输入1*2+3,那么text属性是string,调用哪个函数后就可直接得到6?<br>既通过i=函数名('1*2+3')语句得到i等于6。
 
大概要写一个编译器之类的东西了!:D &nbsp;疯!~~~~~```
 
hehe,这是文本解析器作的事情,自己写一个吧![:)]
 
自己写个过程呀!
 
strtoint()<br>查查帮助,有很多这样的类型转换的<br>四则运算可以用 栈 实现<br>自己写个过程吧<br>good luck!
 
这个好像没有的吧~<br>你可以自己编制一个函数啊~<br>从字符串第一个开始遍历<br>如果该字符大于1小于9 StrToInt(i)<br>等等~
 
简单的计算可以通过SQL完成:<br>with Query1 do<br>var<br>&nbsp; YourValue: Variant;<br>begin<br>&nbsp; Active := False;<br>&nbsp; SQL.Clear;<br>&nbsp; SQL.Add(Format('select %s', [Edit1.Text]);<br>&nbsp; Active := True;<br>&nbsp; YourValue := Fields[0].Value;<br>end;<br><br>对复杂的计算,请自己编一个Parser<br>不过网上有一些免费的,可查一下: formula parser
 
同意lld, 用SQL帮你计算,如 Select 1*2+3<br>
 
没道理啊,要自己解析不是太麻烦了。<br>要是复杂的公式,如求平方根等。<br>最好能象VB的立即窗口中那样输入公式后就可得到值,不知谁对VB比较熟。
 
到网上找个脚本解释器,太多了。解析数学式是小菜一碟
 
用SQL計算最好了
 
有何没道理,其他的解析器不都是人写出来的。<br>不过你可以不写,网上有几个这样的控件。<br><br><br>{<br><br>&nbsp; TFatExpression by Gasper Kozak, gasper.kozak@email.si<br>&nbsp; component is open-source and is free for any use<br>&nbsp; version: 1.01, July 2001<br><br>&nbsp; this is a component used for calculating text-presented expressions<br>&nbsp; features<br>&nbsp; &nbsp; operations: + - * / ^ !<br>&nbsp; &nbsp; parenthesis: ( )<br>&nbsp; &nbsp; variables: their values are requested through OnEvaluate event<br>&nbsp; &nbsp; user-defined functions in format:<br>&nbsp; &nbsp; &nbsp; function_name [ (argument_name [";" argument_name ... ]] "=" expression<br><br>&nbsp; ! parental advisory : bugs included<br>&nbsp; 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>&nbsp; // empty token, numeric, (), +-*/^!, function or variable, ";" character<br>&nbsp; TTokenType = (ttNone, ttNumeric, ttParenthesis, ttOperation, ttString, ttParamDelimitor);<br>&nbsp; TEvaluateOrder = (eoInternalFirst, eoEventFirst);<br>&nbsp; TOnEvaluate = procedure(Sender: TObject; Eval: String; Args: array of Double;<br>&nbsp; &nbsp; ArgCount: Integer; var Value: Double; var Done: Boolean) of object;<br><br>&nbsp; // class used by TExpParser and TExpNode for breaking text into <br>&nbsp; // tokens and building a syntax tree<br>&nbsp; TExpToken = class<br>&nbsp; private<br>&nbsp; &nbsp; FText: String;<br>&nbsp; &nbsp; FTokenType: TTokenType;<br>&nbsp; public<br>&nbsp; &nbsp; property Text: String read FText;<br>&nbsp; &nbsp; property TokenType: TTokenType read FTokenType;<br>&nbsp; end;<br><br>&nbsp; // engine for breaking text into tokens<br>&nbsp; TExpParser = class<br>&nbsp; protected<br>&nbsp; &nbsp; FExpression: String;<br>&nbsp; &nbsp; FTokens: TList;<br>&nbsp; &nbsp; FPos: Integer;<br>&nbsp; private<br>&nbsp; &nbsp; procedure Clear;<br>&nbsp; &nbsp; function GetToken(Index: Integer): TExpToken;<br>&nbsp; &nbsp; procedure SetExpression(const Value: String);<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create;<br>&nbsp; &nbsp; destructor Destroy; override;<br><br>&nbsp; &nbsp; function ReadFirstToken: TExpToken;<br>&nbsp; &nbsp; function ReadNextToken: TExpToken;<br><br>&nbsp; &nbsp; function TokenCount: Integer;<br>&nbsp; &nbsp; property Tokens[Index: Integer]: TExpToken read GetToken;<br>&nbsp; &nbsp; property TokenList: TList read FTokens;<br>&nbsp; &nbsp; property Expression: String read FExpression write SetExpression;<br>&nbsp; end;<br><br>&nbsp; // syntax-tree node. this engine uses a bit upgraded binary-tree<br>&nbsp; TExpNode = class<br>&nbsp; protected<br>&nbsp; &nbsp; FOwner: TObject;<br>&nbsp; &nbsp; FParent: TExpNode;<br>&nbsp; &nbsp; FChildren: TList;<br>&nbsp; &nbsp; FTokens: TList;<br>&nbsp; &nbsp; FLevel: Integer;<br>&nbsp; &nbsp; FToken: TExpToken;<br>&nbsp; &nbsp; FOnEvaluate: TOnEvaluate;<br>&nbsp; private<br>&nbsp; &nbsp; function GetToken(Index: Integer): TExpToken;<br>&nbsp; &nbsp; function GetChildren(Index: Integer): TExpNode;<br>&nbsp; &nbsp; function FindLSOTI: Integer; // LSOTI = least significant operation token index<br>&nbsp; &nbsp; function ParseFunction: Boolean;<br>&nbsp; &nbsp; procedure RemoveSorroundingParenthesis;<br>&nbsp; &nbsp; procedure SplitToChildren(TokenIndex: Integer);<br>&nbsp; &nbsp; function Evaluate: Double;<br>&nbsp; &nbsp; property Children[Index: Integer]: TExpNode read GetChildren;<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create(AOwner: TObject; AParent: TExpNode; Tokens: TList);<br>&nbsp; &nbsp; destructor Destroy; override;<br>&nbsp; &nbsp; procedure Build;<br><br>&nbsp; &nbsp; function TokenCount: Integer;<br>&nbsp; &nbsp; function Calculate: Double;<br>&nbsp; &nbsp; property Tokens[Index: Integer]: TExpToken read GetToken;<br>&nbsp; &nbsp; property Parent: TExpNode read FParent;<br>&nbsp; &nbsp; property Level: Integer read FLevel;<br>&nbsp; &nbsp; property OnEvaluate: TOnEvaluate read FOnEvaluate write FOnEvaluate;<br>&nbsp; end;<br><br>&nbsp; TFunction = class<br>&nbsp; protected<br>&nbsp; &nbsp; FAsString, FName, FHead, FFunction: String;<br>&nbsp; &nbsp; FOwner: TObject;<br>&nbsp; &nbsp; FArgCount: Integer;<br>&nbsp; &nbsp; FArgs: TStringList;<br>&nbsp; &nbsp; FValues: array of Double;<br>&nbsp; private<br>&nbsp; &nbsp; procedure SetAsString(const Value: String);<br>&nbsp; &nbsp; procedure EvalArgs(Sender: TObject; Eval: String; Args: array of Double; ArgCount: Integer; var Value: Double);<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create(AOwner: TObject);<br>&nbsp; &nbsp; destructor Destroy; override;<br>&nbsp; &nbsp; function Call(Values: array of Double): Double;<br>&nbsp; &nbsp; property AsString: String read FAsString write SetAsString;<br>&nbsp; &nbsp; property Name: String read FName;<br>&nbsp; &nbsp; property ArgCount: Integer read FArgCount;<br>&nbsp; &nbsp; property Args: TStringList read FArgs;<br>&nbsp; end;<br><br>&nbsp; // main component, actually only a wrapper for TExpParser, TExpNode and<br>&nbsp; // user input via OnEvaluate event<br>&nbsp; TFatExpression = class(TComponent)<br>&nbsp; protected<br>&nbsp; &nbsp; FInfo, FText: String;<br>&nbsp; &nbsp; FEvaluateOrder: TEvaluateOrder;<br>&nbsp; &nbsp; FOnEvaluate: TOnEvaluate;<br>&nbsp; &nbsp; FValue: Double;<br>&nbsp; &nbsp; FFunctions: TStringList;<br>&nbsp; private<br>&nbsp; &nbsp; procedure Compile;<br>&nbsp; &nbsp; function GetValue: Double;<br>&nbsp; &nbsp; procedure SetInfo(Value: String);<br>&nbsp; &nbsp; procedure Evaluate(Eval: String; Args: array of Double; var Value: Double);<br>&nbsp; &nbsp; function FindFunction(FuncName: String): TFunction;<br>&nbsp; &nbsp; procedure SetFunctions(Value: TStringList);<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create(AOwner: TComponent); override;<br>&nbsp; &nbsp; destructor Destroy; override;<br>&nbsp; &nbsp; property Value: Double read GetValue;<br>&nbsp; published<br>&nbsp; &nbsp; property Text: String read FText write FText;<br>&nbsp; &nbsp; property Info: String read FInfo write SetInfo;<br>&nbsp; &nbsp; property Functions: TStringList read FFunctions write SetFunctions;<br>&nbsp; &nbsp; property EvaluateOrder: TEvaluateOrder read FEvaluateOrder write FEvaluateOrder;<br>&nbsp; &nbsp; property OnEvaluate: TOnEvaluate read FOnEvaluate write FOnEvaluate;<br>&nbsp; end;<br><br><br>procedure Register;<br><br>implementation<br><br>const<br>&nbsp; // supported operations<br>&nbsp; STR_OPERATION = '+-*/^!';<br>&nbsp; // function parameter delimitor<br>&nbsp; STR_PARAMDELIMITOR = ';';<br>&nbsp; // legal variable name characters<br>&nbsp; STR_STRING &nbsp; &nbsp;: array[0..1] of string =<br>&nbsp; &nbsp; ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_',<br>&nbsp; &nbsp; &nbsp;'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$#@0123456789');<br><br><br>procedure Register;<br>begin<br>&nbsp; RegisterComponents('Additional', [TFatExpression]);<br>end;<br><br><br><br>function OperParamateres(const Oper: String): Integer;<br>begin<br>&nbsp; if Pos(Oper, '+-*/^') &gt; 0 then<br>&nbsp; &nbsp; Result := 2 else<br>&nbsp; if Oper = '!' then<br>&nbsp; &nbsp; Result := 1 else<br>&nbsp; &nbsp; Result := 0;<br>end;<br><br>constructor TExpParser.Create;<br>begin<br>&nbsp; inherited Create;<br>&nbsp; FTokens := TList.Create;<br>end;<br><br>destructor TExpParser.Destroy;<br>begin<br>&nbsp; Clear;<br>&nbsp; FTokens.Free;<br>&nbsp; inherited;<br>end;<br><br>procedure TExpParser.Clear;<br>begin<br>&nbsp; while FTokens.Count &gt; 0 do begin<br>&nbsp; &nbsp; TExpToken(FTokens[0]).Free;<br>&nbsp; &nbsp; FTokens.Delete(0);<br>&nbsp; end;<br>end;<br><br>procedure TExpParser.SetExpression(const Value: String);<br>begin<br>&nbsp; FExpression := Trim(Value);<br>end;<br><br>function TExpParser.GetToken(Index: Integer): TExpToken;<br>begin<br>&nbsp; Result := TExpToken(FTokens[Index]);<br>end;<br><br>function TExpParser.ReadFirstToken: TExpToken;<br>begin<br>&nbsp; Clear;<br>&nbsp; FPos := 1;<br>&nbsp; Result := ReadNextToken;<br>end;<br><br>function GetTokenType(S: String; First: Boolean): TTokenType;<br>var Value: Double;<br>&nbsp; P, Error: Integer;<br>begin<br>&nbsp; if (S = '(') or (S = ')') then Result := ttParenthesis else<br>&nbsp; if S = STR_PARAMDELIMITOR then Result := ttParamDelimitor else<br>&nbsp; if Pos(S, STR_OPERATION) &gt; 0 then Result := ttOperation else<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Val(S, Value, Error);<br>&nbsp; &nbsp; &nbsp; if Error = 0 then Result := ttNumeric else<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if First then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P := Pos(S, STR_STRING[0]) else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P := Pos(S, STR_STRING[1]);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if P &gt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result := ttString else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result := ttNone;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>end;<br><br>function TExpParser.ReadNextToken: TExpToken;<br>var Part, Ch: String;<br>&nbsp; FirstType, NextType: TTokenType;<br>&nbsp; Sci: Boolean;<br>begin<br>&nbsp; Result := NIL;<br>&nbsp; if FPos &gt; Length(FExpression) then Exit;<br>&nbsp; Sci := False;<br><br>&nbsp; Part := '';<br>&nbsp; repeat<br>&nbsp; &nbsp; Ch := FExpression[FPos];<br>&nbsp; &nbsp; Inc(FPos);<br>&nbsp; until (Ch &lt;&gt; ' ') or (FPos &gt; Length(FExpression));<br>&nbsp; if FPos - 1 &gt; Length(FExpression) then Exit;<br><br>&nbsp; FirstType := GetTokenType(Ch, True);<br>&nbsp; if FirstType = ttNone then begin<br>&nbsp; &nbsp; raise Exception.CreateFmt('Parse error: illegal character "%s" at position %d.', [Ch, FPos - 1]);<br>&nbsp; &nbsp; Exit;<br>&nbsp; end;<br><br>&nbsp; if FirstType in [ttParenthesis, ttOperation] then begin<br>&nbsp; &nbsp; Result := TExpToken.Create;<br>&nbsp; &nbsp; with Result do begin<br>&nbsp; &nbsp; &nbsp; FText := Ch;<br>&nbsp; &nbsp; &nbsp; FTokenType := FirstType;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FTokens.Add(Result);<br>&nbsp; &nbsp; Exit;<br>&nbsp; end;<br><br>&nbsp; Part := Ch;<br>&nbsp; repeat<br>&nbsp; &nbsp; Ch := FExpression[FPos];<br>&nbsp; &nbsp; NextType := GetTokenType(Ch, False);<br><br>&nbsp; &nbsp; if<br>&nbsp; &nbsp; &nbsp; &nbsp; (NextType = FirstType) or<br>&nbsp; &nbsp; &nbsp; &nbsp;((FirstType = ttString) and (NextType = ttNumeric)) or<br>&nbsp; &nbsp; &nbsp; &nbsp;((FirstType = ttNumeric) and (NextType = ttString) and (Ch = 'E') and (Sci = False)) or<br>&nbsp; &nbsp; &nbsp; &nbsp;((FirstType = ttNumeric) and (NextType = ttOperation) and (Ch = '-') and (Sci = True))<br>&nbsp; &nbsp; then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Part := Part + Ch;<br>&nbsp; &nbsp; &nbsp; &nbsp; if (FirstType = ttNumeric) and (NextType = ttString) and (Ch = 'E') then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sci := True;<br>&nbsp; &nbsp; &nbsp; end else<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := TExpToken.Create;<br>&nbsp; &nbsp; &nbsp; &nbsp; with Result do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FText := Part;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FTokenType := FirstType;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; FTokens.Add(Result);<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; Inc(FPos);<br>&nbsp; until FPos &gt; Length(FExpression);<br><br>&nbsp; Result := TExpToken.Create;<br>&nbsp; with Result do begin<br>&nbsp; &nbsp; FText := Part;<br>&nbsp; &nbsp; FTokenType := FirstType;<br>&nbsp; end;<br>&nbsp; FTokens.Add(Result);<br>end;<br><br>function TExpParser.TokenCount: Integer;<br>begin<br>&nbsp; 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>&nbsp; inherited Create;<br><br>&nbsp; FOwner := AOwner;<br>&nbsp; FParent := AParent;<br>&nbsp; if FParent = NIL then<br>&nbsp; &nbsp; FLevel := 0 else<br>&nbsp; &nbsp; FLevel := FParent.Level + 1;<br><br>&nbsp; FTokens := TList.Create;<br>&nbsp; I := 0;<br>&nbsp; while I &lt; Tokens.Count do begin<br>&nbsp; &nbsp; FTokens.Add(Tokens);<br>&nbsp; &nbsp; Inc(I);<br>&nbsp; end;<br><br>&nbsp; FChildren := TList.Create;<br><br>&nbsp; if Tokens.Count = 1 then<br>&nbsp; &nbsp; FToken := Tokens[0];<br>end;<br><br>destructor TExpNode.Destroy;<br>var Child: TExpNode;<br>begin<br>&nbsp; if Assigned(FChildren) then begin<br>&nbsp; &nbsp; while FChildren.Count &gt; 0 do begin<br>&nbsp; &nbsp; &nbsp; Child := Children[FChildren.Count - 1];<br>&nbsp; &nbsp; &nbsp; FreeAndNil(Child);<br>&nbsp; &nbsp; &nbsp; FChildren.Delete(FChildren.Count - 1);<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; FreeAndNil(FChildren);<br>&nbsp; end;<br><br>&nbsp; FTokens.Free;<br>&nbsp; inherited;<br>end;<br><br>procedure TExpNode.RemoveSorroundingParenthesis;<br>var First, Last, Lvl, I: Integer;<br>&nbsp; Sorrounding: Boolean;<br>begin<br>&nbsp; First := 0;<br>&nbsp; Last := TokenCount - 1;<br>&nbsp; while Last &gt; First do begin<br>&nbsp; &nbsp; if (Tokens[First].TokenType = ttParenthesis) and (Tokens[Last].TokenType = ttParenthesis) and<br>&nbsp; &nbsp; &nbsp; &nbsp;(Tokens[First].Text = '(') and (Tokens[Last].Text = ')') then begin<br><br>&nbsp; &nbsp; &nbsp; Lvl := 0;<br>&nbsp; &nbsp; &nbsp; I := 0;<br>&nbsp; &nbsp; &nbsp; Sorrounding := True;<br>&nbsp; &nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; &nbsp; if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = '(') then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Inc(Lvl) else<br>&nbsp; &nbsp; &nbsp; &nbsp; if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = ')') then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dec(Lvl);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if (Lvl = 0) and (I &lt; TokenCount - 1) then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sorrounding := False;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Break;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; Inc(I);<br>&nbsp; &nbsp; &nbsp; until I = TokenCount;<br><br>&nbsp; &nbsp; &nbsp; if Sorrounding then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; FTokens.Delete(Last);<br>&nbsp; &nbsp; &nbsp; &nbsp; FTokens.Delete(First);<br>&nbsp; &nbsp; &nbsp; end else<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end else<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; First := 0;<br>&nbsp; &nbsp; Last := TokenCount - 1;<br>&nbsp; end;<br>end;<br><br>procedure TExpNode.Build;<br>var LSOTI: Integer;<br>begin<br>&nbsp; if TokenCount &lt; 2 then<br>&nbsp; &nbsp; Exit;<br>&nbsp; RemoveSorroundingParenthesis;<br>&nbsp; if TokenCount &lt; 2 then<br>&nbsp; &nbsp; Exit;<br><br>&nbsp; LSOTI := FindLSOTI;<br>&nbsp; if LSOTI &lt; 0 then begin<br>&nbsp; &nbsp; if ParseFunction then Exit;<br>&nbsp; &nbsp; raise Exception.Create('Compile error: syntax fault.');<br>&nbsp; &nbsp; Exit;<br>&nbsp; end;<br>&nbsp; SplitToChildren(LSOTI);<br>end;<br><br>function TExpNode.ParseFunction: Boolean;<br>var Func: Boolean;<br>&nbsp; I, Delimitor, DelimitorLevel: Integer;<br>&nbsp; FChild: TExpNode;<br>&nbsp; FList: TList;<br>begin<br>&nbsp; Result := False;<br>&nbsp; if TokenCount &lt; 4 then Exit;<br><br>&nbsp; Func := (Tokens[0].TokenType = ttString) and<br>&nbsp; &nbsp; (Tokens[1].TokenType = ttParenthesis) and (Tokens[TokenCount - 1].TokenType = ttParenthesis);<br><br>&nbsp; if not Func then Exit;<br><br>&nbsp; FToken := Tokens[0];<br>&nbsp; with FTokens do begin<br>&nbsp; &nbsp; Delete(TokenCount - 1);<br>&nbsp; &nbsp; Delete(1);<br>&nbsp; end;<br><br>&nbsp; FList := TList.Create;<br>&nbsp; try<br>&nbsp; &nbsp; while TokenCount &gt; 1 do begin<br>&nbsp; &nbsp; &nbsp; Delimitor := - 1;<br>&nbsp; &nbsp; &nbsp; DelimitorLevel := 0;<br>&nbsp; &nbsp; &nbsp; for I := 1 to TokenCount - 1 do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = '(') then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Inc(DelimitorLevel) else<br>&nbsp; &nbsp; &nbsp; &nbsp; if (Tokens.TokenType = ttParenthesis) and (Tokens.Text = ')') then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dec(DelimitorLevel) else<br>&nbsp; &nbsp; &nbsp; &nbsp; if (Tokens.TokenType = ttParamDelimitor) and (DelimitorLevel = 0) then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Delimitor := I - 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FTokens.Delete(I);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Break;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if DelimitorLevel &lt; 0 then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('Function parse error.');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; if Delimitor = -1 then Delimitor := TokenCount - 1;<br>&nbsp; &nbsp; &nbsp; for I := 1 to Delimitor do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; FList.Add(Tokens[1]);<br>&nbsp; &nbsp; &nbsp; &nbsp; FTokens.Delete(1);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; FChild := TExpNode.Create(FOwner, Self, FList);<br>&nbsp; &nbsp; &nbsp; FList.Clear;<br>&nbsp; &nbsp; &nbsp; FChild.Build;<br>&nbsp; &nbsp; &nbsp; FChildren.Add(FChild);<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; FList.Free;<br>&nbsp; end;<br>&nbsp; Result := True;<br>end;<br><br>procedure TExpNode.SplitToChildren(TokenIndex: Integer);<br>var Left, Right: TList;<br>&nbsp; I: Integer;<br>&nbsp; FChild: TExpNode;<br>begin<br>&nbsp; Left := TList.Create;<br>&nbsp; Right := TList.Create;<br><br>&nbsp; try<br>&nbsp; &nbsp; if TokenIndex &lt; TokenCount - 1 then<br>&nbsp; &nbsp; &nbsp; for I := TokenCount - 1 downto TokenIndex + 1 do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Right.Insert(0, FTokens);<br>&nbsp; &nbsp; &nbsp; &nbsp; FTokens.Delete(I);<br>&nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; if Right.Count &gt; 0 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; FChild := TExpNode.Create(FOwner, Self, Right);<br>&nbsp; &nbsp; &nbsp; FChildren.Insert(0, FChild);<br>&nbsp; &nbsp; &nbsp; FChild.Build;<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; if TokenIndex &gt; 0 then<br>&nbsp; &nbsp; &nbsp; for I := TokenIndex - 1 downto 0 do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Left.Insert(0, FTokens);<br>&nbsp; &nbsp; &nbsp; &nbsp; FTokens.Delete(I);<br>&nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; FChild := TExpNode.Create(FOwner, Self, Left);<br>&nbsp; &nbsp; FChildren.Insert(0, FChild);<br>&nbsp; &nbsp; FChild.Build;<br>&nbsp; finally<br>&nbsp; &nbsp; FToken := Tokens[0];<br>&nbsp; &nbsp; Left.Free;<br>&nbsp; &nbsp; Right.Free;<br>&nbsp; end;<br>end;<br><br>function TExpNode.GetChildren(Index: Integer): TExpNode;<br>begin<br>&nbsp; Result := TExpNode(FChildren[Index]);<br>end;<br><br>function TExpNode.FindLSOTI: Integer;<br>var Lvl, I, LSOTI, NewOperPriority, OperPriority: Integer;<br>begin<br>&nbsp; Lvl := 0; // Lvl = parenthesis level<br>&nbsp; I := 0;<br>&nbsp; LSOTI := - 1;<br>&nbsp; OperPriority := 9;<br><br>&nbsp; repeat<br>&nbsp; &nbsp; if Tokens.TokenType = ttParenthesis then begin<br>&nbsp; &nbsp; &nbsp; if Tokens.Text = '(' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Inc(Lvl) else<br>&nbsp; &nbsp; &nbsp; if Tokens.Text = ')' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Dec(Lvl);<br><br>&nbsp; &nbsp; &nbsp; if Lvl &lt; 0 then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; //raise Exception.CreateFmt('Parenthesis mismatch at level %d, token %d.', [Level, I]);<br>&nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('Compile error: parenthesis mismatch.');<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; if (Tokens.TokenType = ttOperation) and (Lvl = 0) then begin<br>&nbsp; &nbsp; &nbsp; NewOperPriority := Pos(Tokens.Text, STR_OPERATION);<br>&nbsp; &nbsp; &nbsp; if NewOperPriority &lt;= OperPriority then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; OperPriority := NewOperPriority;<br>&nbsp; &nbsp; &nbsp; &nbsp; LSOTI := I;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; Inc(I);<br>&nbsp; until I &gt;= TokenCount;<br><br>&nbsp; Result := LSOTI;<br>end;<br><br>function Exl(Value: Integer): Double;<br>begin<br>&nbsp; if Value &lt;= 1 then<br>&nbsp; &nbsp; Result := Value else<br>&nbsp; &nbsp; Result := Value * Exl(Value - 1);<br>end;<br><br>function TExpNode.Evaluate: Double;<br>var Args: array of Double;<br>&nbsp; Count, I: Integer;<br>&nbsp; Done: Boolean;<br>begin<br>&nbsp; Result := 0;<br>&nbsp; if FToken.TokenType = ttString then begin<br>&nbsp; &nbsp; Count := FChildren.Count;<br>&nbsp; &nbsp; SetLength(Args, Count);<br>&nbsp; &nbsp; for I := 0 to Count - 1 do<br>&nbsp; &nbsp; &nbsp; Args := Children.Calculate;<br><br>&nbsp; &nbsp; if Assigned(FOnEvaluate) then<br>&nbsp; &nbsp; &nbsp; FOnEvaluate(Self, FToken.Text, Args, High(Args) + 1, Result, Done) else<br>&nbsp; &nbsp; if FOwner is TFatExpression then<br>&nbsp; &nbsp; &nbsp; TFatExpression(FOwner).Evaluate(FToken.Text, Args, Result) else<br>&nbsp; &nbsp; if FOwner is TFunction then<br>&nbsp; &nbsp; &nbsp; TFunction(FOwner).EvalArgs(Self, FToken.Text, Args, High(Args) + 1, Result);<br>&nbsp; end;<br>end;<br><br>function TExpNode.Calculate: Double;<br>var Error: Integer;<br>&nbsp; DivX, DivY: Double;<br>begin<br>&nbsp; Result := 0;<br>&nbsp; if (FToken = NIL) or (TokenCount = 0) then<br>&nbsp; &nbsp; Exit;<br><br>&nbsp; if TokenCount = 1 then begin<br>&nbsp; &nbsp; if FToken.TokenType = ttNumeric then begin<br>&nbsp; &nbsp; &nbsp; Val(FToken.Text, Result, Error);<br>&nbsp; &nbsp; end else<br>&nbsp; &nbsp; if FToken.TokenType = ttString then begin<br>&nbsp; &nbsp; &nbsp; Result := Evaluate;<br>&nbsp; &nbsp; end else<br>&nbsp; &nbsp; if FToken.TokenType = ttOperation then begin<br>&nbsp; &nbsp; &nbsp; if FChildren.Count &lt;&gt; OperParamateres(FToken.Text) then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('Calculate error: syntax tree fault.');<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; if FToken.Text = '+' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := Children[0].Calculate + Children[1].Calculate else<br>&nbsp; &nbsp; &nbsp; if FToken.Text = '-' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := Children[0].Calculate - Children[1].Calculate else<br>&nbsp; &nbsp; &nbsp; if FToken.Text = '*' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := Children[0].Calculate * Children[1].Calculate else<br>&nbsp; &nbsp; &nbsp; if FToken.Text = '/' then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; DivX := Children[0].Calculate;<br>&nbsp; &nbsp; &nbsp; &nbsp; DivY := Children[1].Calculate;<br>&nbsp; &nbsp; &nbsp; &nbsp; if DivY &lt;&gt; 0 then Result := DivX / DivY else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception.CreateFmt('Calculate error: "%f / %f" divison by zero.', [DivX, DivY]);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end else<br>&nbsp; &nbsp; &nbsp; if FToken.Text = '^' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := Power(Children[0].Calculate, Children[1].Calculate) else<br>&nbsp; &nbsp; &nbsp; if FToken.Text = '!' then<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := Exl(Round(Children[0].Calculate));<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br>function TExpNode.GetToken(Index: Integer): TExpToken;<br>begin<br>&nbsp; Result := TExpToken(FTokens[Index]);<br>end;<br><br>function TExpNode.TokenCount: Integer;<br>begin<br>&nbsp; Result := FTokens.Count;<br>end;<br><br><br><br><br><br><br><br><br>constructor TFunction.Create(AOwner: TObject);<br>begin<br>&nbsp; inherited Create;<br>&nbsp; FOwner := AOwner;<br>&nbsp; FAsString := '';<br>&nbsp; FName := '';<br>&nbsp; FArgCount := 0;<br>&nbsp; FArgs := TStringList.Create;<br>end;<br><br>destructor TFunction.Destroy;<br>begin<br>&nbsp; FArgs.Free;<br>&nbsp; inherited;<br>end;<br><br>function TFunction.Call(Values: array of Double): Double;<br>var Token: TExpToken;<br>&nbsp; Tree: TExpNode;<br>&nbsp; Parser: TExpParser;<br>&nbsp; I: Integer;<br>begin<br>&nbsp; SetLength(FValues, High(Values) + 1);<br>&nbsp; for I := 0 to High(Values) do<br>&nbsp; &nbsp; FValues := Values;<br>&nbsp; &nbsp; <br>&nbsp; Parser := TExpParser.Create;<br>&nbsp; try<br>&nbsp; &nbsp; Parser.Expression := FFunction;<br>&nbsp; &nbsp; Token := Parser.ReadFirstToken;<br>&nbsp; &nbsp; while Token &lt;&gt; NIL do Token := Parser.ReadNextToken;<br><br>&nbsp; &nbsp; Tree := TExpNode.Create(Self, NIL, Parser.TokenList);<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; with Tree do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Build;<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := Calculate;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; finally<br>&nbsp; &nbsp; &nbsp; Tree.Free;<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; Parser.Free;<br>&nbsp; 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>&nbsp; for I := 0 to FArgs.Count - 1 do<br>&nbsp; &nbsp; &nbsp;if UpperCase(FArgs) = UpperCase(Eval) then begin<br>&nbsp; &nbsp; &nbsp; Value := FValues;<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br><br>&nbsp; if FOwner is TFatExpression then<br>&nbsp; &nbsp; TFatExpression(FOwner).Evaluate(Eval, Args, Value);<br>end;<br><br>procedure TFunction.SetAsString(const Value: String);<br>var Head: String;<br>&nbsp; HeadPos: Integer;<br>&nbsp; Parser: TExpParser;<br>&nbsp; Token: TExpToken;<br>&nbsp; ExpectParenthesis, ExpectDelimitor: Boolean;<br>begin<br>&nbsp; FArgs.Clear;<br>&nbsp; FArgCount := 0;<br>&nbsp; FAsString := Value;<br>&nbsp; FHead := '';<br>&nbsp; FFunction := '';<br>&nbsp; FName := '';<br><br>&nbsp; HeadPos := Pos('=', FAsString);<br>&nbsp; if HeadPos = 0 then Exit;<br>&nbsp; Head := Copy(FAsString, 1, HeadPos - 1);<br>&nbsp; FFunction := FAsString;<br>&nbsp; Delete(FFunction, 1, HeadPos);<br>&nbsp; Parser := TExpParser.Create;<br>&nbsp; try<br>&nbsp; &nbsp; Parser.Expression := Head;<br>&nbsp; &nbsp; Token := Parser.ReadFirstToken;<br>&nbsp; &nbsp; if (Token = NIL) or (Token.TokenType &lt;&gt; ttString) then begin<br>&nbsp; &nbsp; &nbsp; raise Exception.CreateFmt('Function "%s" is not valid.', [FAsString]);<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FName := Token.Text;<br><br>&nbsp; &nbsp; Token := Parser.ReadNextToken;<br>&nbsp; &nbsp; if Token = NIL then Exit;<br>&nbsp; &nbsp; if Token.TokenType = ttParenthesis then begin<br>&nbsp; &nbsp; &nbsp; if Token.Text = '(' then ExpectParenthesis := True else<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; raise Exception.CreateFmt('Function header "%s" is not valid.', [Head]);<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end else<br>&nbsp; &nbsp; ExpectParenthesis := False;<br><br>&nbsp; &nbsp; ExpectDelimitor := False;<br>&nbsp; &nbsp; while Token &lt;&gt; NIL do begin<br>&nbsp; &nbsp; &nbsp; Token := Parser.ReadNextToken;<br>&nbsp; &nbsp; &nbsp; if Token &lt;&gt; NIL then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if Token.TokenType = ttParenthesis then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ExpectParenthesis and (Token.Text = ')') then Exit else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception.CreateFmt('Function header "%s" is not valid.', [Head]);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if ExpectDelimitor then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Token.TokenType &lt;&gt; ttParamDelimitor) and (Token.TokenType &lt;&gt; ttParenthesis) then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('Function parse error: delimitor ";" expected between arguments.');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ExpectDelimitor := False;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Continue;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if Token.TokenType = ttString then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FArgs.Add(Token.Text);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FArgCount := FArgs.Count;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ExpectDelimitor := True;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if ExpectParenthesis then<br>&nbsp; &nbsp; &nbsp; raise Exception.CreateFmt('Function header "%s" is not valid.', [Head]);<br>&nbsp; finally<br>&nbsp; &nbsp; Parser.Free;<br>&nbsp; end;<br>end;<br><br><br><br><br><br>constructor TFatExpression.Create;<br>begin<br>&nbsp; inherited;<br>&nbsp; FText := '';<br>&nbsp; FInfo := 'TFatExpression v1.0 by gasper.kozak@email.si';<br>&nbsp; FFunctions := TStringList.Create;<br>end;<br><br>destructor TFatExpression.Destroy;<br>begin<br>&nbsp; FFunctions.Free;<br>&nbsp; inherited;<br>end;<br><br>procedure TFatExpression.Compile;<br>var Token: TExpToken;<br>&nbsp; Tree: TExpNode;<br>&nbsp; Parser: TExpParser;<br>begin<br>&nbsp; Parser := TExpParser.Create;<br>&nbsp; try<br>&nbsp; &nbsp; Parser.Expression := FText;<br>&nbsp; &nbsp; Token := Parser.ReadFirstToken;<br>&nbsp; &nbsp; while Token &lt;&gt; NIL do<br>&nbsp; &nbsp; &nbsp; Token := Parser.ReadNextToken;<br><br>&nbsp; &nbsp; Tree := TExpNode.Create(Self, NIL, Parser.TokenList);<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; with Tree do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Build;<br>&nbsp; &nbsp; &nbsp; &nbsp; FValue := Calculate;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; finally<br>&nbsp; &nbsp; &nbsp; Tree.Free;<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; Parser.Free;<br>&nbsp; end;<br>end;<br><br>function TFatExpression.FindFunction(FuncName: String): TFunction;<br>var F: TFunction;<br>&nbsp; I: Integer;<br>begin<br>&nbsp; Result := NIL;<br>&nbsp; for I := 0 to FFunctions.Count - 1 do<br>&nbsp; &nbsp; if Trim(FFunctions) &lt;&gt; '' then begin<br>&nbsp; &nbsp; &nbsp; F := TFunction.Create(Self);<br>&nbsp; &nbsp; &nbsp; F.AsString := FFunctions;<br>&nbsp; &nbsp; &nbsp; if UpperCase(F.Name) = UpperCase(FuncName) then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := F;<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; F.Free;<br>&nbsp; &nbsp; end;<br>end;<br><br>procedure TFatExpression.SetInfo(Value: String);<br>begin<br>&nbsp; //<br>end;<br><br>procedure TFatExpression.Evaluate(Eval: String; Args: array of Double; var Value: Double);<br>var Func: TFunction;<br>&nbsp; Done: Boolean;<br>begin<br>&nbsp; Done := False;<br>&nbsp; if (EvaluateOrder = eoEventFirst) and Assigned(FOnEvaluate) then begin<br>&nbsp; &nbsp; FOnEvaluate(Self, Eval, Args, High(Args) + 1, Value, Done);<br>&nbsp; &nbsp; if Done then Exit;<br>&nbsp; end else<br>&nbsp; Value := 0;<br><br>&nbsp; Func := FindFunction(Eval);<br>&nbsp; if Func &lt;&gt; NIL then begin<br>&nbsp; &nbsp; Value := Func.Call(Args);<br>&nbsp; &nbsp; Func.Free;<br>&nbsp; &nbsp; Exit;<br>&nbsp; end;<br><br>&nbsp; if (EvaluateOrder = eoInternalFirst) and Assigned(FOnEvaluate) then<br>&nbsp; &nbsp; FOnEvaluate(Self, Eval, Args, High(Args) + 1, Value, Done) else<br>&nbsp; &nbsp; Value := 0;<br>end;<br><br>function TFatExpression.GetValue: Double;<br>begin<br>&nbsp; Compile;<br>&nbsp; Result := FValue;<br>end;<br><br>procedure TFatExpression.SetFunctions(Value: TStringList);<br>begin<br>&nbsp; FFunctions.Assign(Value);<br>end;<br><br><br>end.<br><br>这是一个带源码的,但是功能还不行,我试过一下,好象不支持括号的嵌套。<br>可以应付简单的计算。你可以在此基础上修改。<br>
 
请大家推荐几个脚本解释器
 
看我回答的帖子
 
你可以用intTOstr(strTOint(edit1.text))来得到所计算的值
 
数据结构与算法要学好!
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
835
SUNSTONE的Delphi笔记
S
后退
顶部