00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Expression classes and interfaces }
00005 { }
00006 { Originally written by Sergey Seroukhov }
00007 { }
00008 {*********************************************************}
00009
00010 {@********************************************************}
00011 { Copyright (c) 1999-2006 Zeos Development Group }
00012 { }
00013 { License Agreement: }
00014 { }
00015 { This library is distributed in the hope that it will be }
00016 { useful, but WITHOUT ANY WARRANTY; without even the }
00017 { implied warranty of MERCHANTABILITY or FITNESS FOR }
00018 { A PARTICULAR PURPOSE. See the GNU Lesser General }
00019 { Public License for more details. }
00020 { }
00021 { The source code of the ZEOS Libraries and packages are }
00022 { distributed under the Library GNU General Public }
00023 { License (see the file COPYING / COPYING.ZEOS) }
00024 { with the following modification: }
00025 { As a special exception, the copyright holders of this }
00026 { library give you permission to link this library with }
00027 { independent modules to produce an executable, }
00028 { regardless of the license terms of these independent }
00029 { modules, and to copy and distribute the resulting }
00030 { executable under terms of your choice, provided that }
00031 { you also meet, for each linked independent module, }
00032 { the terms and conditions of the license of that module. }
00033 { An independent module is a module which is not derived }
00034 { from or based on this library. If you modify this }
00035 { library, you may extend this exception to your version }
00036 { of the library, but you are not obligated to do so. }
00037 { If you do not wish to do so, delete this exception }
00038 { statement from your version. }
00039 { }
00040 { }
00041 { The project web site is located on: }
00042 { http:
00043 { http:
00044 { svn:
00045 { }
00046 { http:
00047 { http:
00048 { }
00049 { }
00050 { }
00051 { Zeos Development Group. }
00052 {********************************************************@}
00053
00054 unit ZExpression;
00055
00056 interface
00057
00058 {$I ZCore.inc}
00059
00060 uses SysUtils, Classes, ZClasses, ZCompatibility, ZVariant, ZTokenizer;
00061
00062 type
00063 {** Defines an expression exception. }
00064 TZExpressionError = class (Exception);
00065
00066 {** Defines an execution stack object. }
00067 TZExecutionStack = class (TObject)
00068 private
00069 FValues: TZVariantDynArray;
00070 FCount: Integer;
00071 FCapacity: Integer;
00072
00073 function GetValue(Index: Integer): TZVariant;
00074 public
00075 constructor Create;
00076
00077 function Pop: TZVariant;
00078 function Peek: TZVariant;
00079 procedure Push(Value: TZVariant);
00080 function GetParameter(Index: Integer): TZVariant;
00081 procedure Swap;
00082
00083 procedure Clear;
00084
00085 property Count: Integer read FCount;
00086 property Values[Index: Integer]: TZVariant read GetValue;
00087 end;
00088
00089 {** Defines a list of variables. }
00090 IZVariablesList = interface (IZInterface)
00091 ['{F4347F46-32F3-4021-B6DB-7A39BF171275}']
00092
00093 function GetCount: Integer;
00094 function GetName(Index: Integer): string;
00095 function GetValue(Index: Integer): TZVariant;
00096 procedure SetValue(Index: Integer; const Value: TZVariant);
00097 function GetValueByName(const Name: string): TZVariant;
00098 procedure SetValueByName(const Name: string; const Value: TZVariant);
00099
00100 procedure Add(const Name: string; const Value: TZVariant);
00101 procedure Remove(const Name: string);
00102 function FindByName(const Name: string): Integer;
00103
00104 procedure ClearValues;
00105 procedure Clear;
00106
00107 property Count: Integer read GetCount;
00108 property Names[Index: Integer]: string read GetName;
00109 property Values[Index: Integer]: TZVariant read GetValue write SetValue;
00110 property NamedValues[const Index: string]: TZVariant read GetValueByName
00111 write SetValueByName;
00112 end;
00113
00114 {** Defines a function interface. }
00115 IZFunction = interface (IZInterface)
00116 ['{E9B3AFF9-6CD9-49C8-AB66-C8CF60ED8686}']
00117
00118 function GetName: string;
00119 function Execute(Stack: TZExecutionStack;
00120 VariantManager: IZVariantManager): TZVariant;
00121
00122 property Name: string read GetName;
00123 end;
00124
00125 {** Defines a list of functions. }
00126 IZFunctionsList = interface (IZInterface)
00127 ['{54453054-F012-475B-84C3-7E5C46187FDB}']
00128
00129 function GetCount: Integer;
00130 function GetName(Index: Integer): string;
00131 function GetFunction(Index: Integer): IZFunction;
00132
00133 procedure Add(Func: IZFunction);
00134 procedure Remove(const Name: string);
00135 function FindByName(const Name: string): Integer;
00136 procedure Clear;
00137
00138 property Count: Integer read GetCount;
00139 property Names[Index: Integer]: string read GetName;
00140 property Functions[Index: Integer]: IZFunction read GetFunction;
00141 end;
00142
00143 {** Defines an interface to expression calculator. }
00144 IZExpression = interface (IZInterface)
00145 ['{26F9D379-5618-446C-8999-D50FBB2F8560}']
00146
00147 function GetTokenizer: IZTokenizer;
00148 procedure SetTokenizer(Value: IZTokenizer);
00149 function GetExpression: string;
00150 procedure SetExpression(const Value: string);
00151 function GetVariantManager: IZVariantManager;
00152 procedure SetVariantManager(Value: IZVariantManager);
00153 function GetDefaultVariables: IZVariablesList;
00154 procedure SetDefaultVariables(Value: IZVariablesList);
00155 function GetDefaultFunctions: IZFunctionsList;
00156 procedure SetDefaultFunctions(Value: IZFunctionsList);
00157 function GetAutoVariables: Boolean;
00158 procedure SetAutoVariables(Value: Boolean);
00159
00160 function Evaluate: TZVariant;
00161 function Evaluate2(Variables: IZVariablesList): TZVariant;
00162 function Evaluate3(Variables: IZVariablesList;
00163 Functions: IZFunctionsList): TZVariant;
00164 function Evaluate4(Variables: IZVariablesList;
00165 Functions: IZFunctionsList; Stack: TZExecutionStack): TZVariant;
00166
00167 procedure CreateVariables(Variables: IZVariablesList);
00168 procedure Clear;
00169
00170 property Tokenizer: IZTokenizer read GetTokenizer write SetTokenizer;
00171 property Expression: string read GetExpression write SetExpression;
00172 property VariantManager: IZVariantManager read GetVariantManager
00173 write SetVariantManager;
00174 property DefaultVariables: IZVariablesList read GetDefaultVariables
00175 write SetDefaultVariables;
00176 property DefaultFunctions: IZFunctionsList read GetDefaultFunctions
00177 write SetDefaultFunctions;
00178 property AutoVariables: Boolean read GetAutoVariables
00179 write SetAutoVariables;
00180 end;
00181
00182 {** Implements an expression calculator class. }
00183 TZExpression = class (TInterfacedObject, IZExpression)
00184 private
00185 FTokenizer: IZTokenizer;
00186 FDefaultVariables: IZVariablesList;
00187 FDefaultFunctions: IZFunctionsList;
00188 FVariantManager: IZVariantManager;
00189 FParser: TObject;
00190 FAutoVariables: Boolean;
00191
00192 function GetTokenizer: IZTokenizer;
00193 procedure SetTokenizer(Value: IZTokenizer);
00194 function GetExpression: string;
00195 procedure SetExpression(const Value: string);
00196 function GetVariantManager: IZVariantManager;
00197 procedure SetVariantManager(Value: IZVariantManager);
00198 function GetDefaultVariables: IZVariablesList;
00199 procedure SetDefaultVariables(Value: IZVariablesList);
00200 function GetDefaultFunctions: IZFunctionsList;
00201 procedure SetDefaultFunctions(Value: IZFunctionsList);
00202 function GetAutoVariables: Boolean;
00203 procedure SetAutoVariables(Value: Boolean);
00204 public
00205 constructor Create;
00206 constructor CreateWithExpression(const Expression: string);
00207 destructor Destroy; override;
00208
00209 function Evaluate: TZVariant;
00210 function Evaluate2(Variables: IZVariablesList): TZVariant;
00211 function Evaluate3(Variables: IZVariablesList;
00212 Functions: IZFunctionsList): TZVariant;
00213 function Evaluate4(Variables: IZVariablesList;
00214 Functions: IZFunctionsList; Stack: TZExecutionStack): TZVariant;
00215
00216 procedure CreateVariables(Variables: IZVariablesList);
00217 procedure Clear;
00218
00219 property Expression: string read GetExpression write SetExpression;
00220 property VariantManager: IZVariantManager read GetVariantManager
00221 write SetVariantManager;
00222 property DefaultVariables: IZVariablesList read GetDefaultVariables
00223 write SetDefaultVariables;
00224 property DefaultFunctions: IZFunctionsList read GetDefaultFunctions
00225 write SetDefaultFunctions;
00226 property AutoVariables: Boolean read GetAutoVariables
00227 write SetAutoVariables;
00228 end;
00229
00230 implementation
00231
00232 uses
00233 ZMessages, ZExprToken, ZExprParser, ZVariables, ZFunctions, ZMatchPattern;
00234
00235 { TZExecutionStack }
00236
00237 {**
00238 Creates this object.
00239 }
00240 constructor TZExecutionStack.Create;
00241 begin
00242 FCapacity := 100;
00243 SetLength(FValues, FCapacity);
00244 FCount := 0;
00245 end;
00246
00247 {**
00248 Gets a value from absolute position in the stack.
00249 @param Index a value index.
00250 @returns a variant value from requested position.
00251 }
00252 function TZExecutionStack.GetValue(Index: Integer): TZVariant;
00253 begin
00254 Result := FValues[Index];
00255 end;
00256
00257 {**
00258 Gets a value from the top of the stack without removing it.
00259 @returns a value from the top.
00260 }
00261 function TZExecutionStack.Peek: TZVariant;
00262 begin
00263 if FCount > 0 then
00264 Result := FValues[FCount - 1]
00265 else Result := NullVariant;
00266 end;
00267
00268 {**
00269 Gets a function parameter by index.
00270 @param a function parameter index. O is used for parameter count.
00271 @returns a parameter value.
00272 }
00273 function TZExecutionStack.GetParameter(Index: Integer): TZVariant;
00274 begin
00275 if FCount <= Index then
00276 raise TZExpressionError.Create(SStackIsEmpty);
00277 Result := FValues[FCount - Index - 1];
00278 end;
00279
00280 {**
00281 Gets a value from the top and removes it from the stack.
00282 @returns a value from the top.
00283 }
00284 function TZExecutionStack.Pop: TZVariant;
00285 begin
00286 Result := NullVariant;
00287 if FCount <= 0 then
00288 raise TZExpressionError.Create(SStackIsEmpty);
00289 Dec(FCount);
00290 Result := FValues[FCount];
00291 end;
00292
00293 {**
00294 Puts a value to the top of the stack.
00295 }
00296 procedure TZExecutionStack.Push(Value: TZVariant);
00297 begin
00298 if FCapacity = FCount then
00299 begin
00300 Inc(FCapacity, 100);
00301 SetLength(FValues, FCapacity);
00302 end;
00303 DefVarManager.Assign(Value, FValues[FCount]);
00304 Inc(FCount);
00305 end;
00306
00307 {**
00308 Swaps two values on the top of the stack.
00309 }
00310 procedure TZExecutionStack.Swap;
00311 var
00312 Temp: TZVariant;
00313 begin
00314 if FCount <= 1 then
00315 raise TZExpressionError.Create(SStackIsEmpty);
00316
00317 Temp := FValues[FCount - 1];
00318 FValues[FCount - 1] := FValues[FCount - 2];
00319 FValues[FCount - 2] := Temp;
00320 end;
00321
00322 {**
00323 Clears this stack.
00324 }
00325 procedure TZExecutionStack.Clear;
00326 begin
00327 FCount := 0;
00328 end;
00329
00330 { TZExpression }
00331
00332 {**
00333 Creates this expression calculator object.
00334 }
00335 constructor TZExpression.Create;
00336 begin
00337 FTokenizer := TZExpressionTokenizer.Create;
00338 FDefaultVariables := TZVariablesList.Create;
00339 FDefaultFunctions := TZDefaultFunctionsList.Create;
00340 FVariantManager := TZSoftVariantManager.Create;
00341 FParser := TZExpressionParser.Create(FTokenizer);
00342 FAutoVariables := True;
00343 end;
00344
00345 {**
00346 Creates this expression calculator and assignes expression string.
00347 @param Expression an expression string.
00348 }
00349 constructor TZExpression.CreateWithExpression(const Expression: string);
00350 begin
00351 Create;
00352 SetExpression(Expression);
00353 end;
00354
00355 {**
00356 Destroys this object and cleanups the memory.
00357 }
00358 destructor TZExpression.Destroy;
00359 begin
00360 FTokenizer := nil;
00361 FDefaultVariables := nil;
00362 FDefaultFunctions := nil;
00363 FVariantManager := nil;
00364 FParser.Free;
00365
00366 inherited Destroy;
00367 end;
00368
00369 {**
00370 Gets the current auto variables create flag.
00371 @returns the auto variables create flag.
00372 }
00373 function TZExpression.GetAutoVariables: Boolean;
00374 begin
00375 Result := FAutoVariables;
00376 end;
00377
00378 {**
00379 Sets a new auto variables create flag.
00380 @param value a new auto variables create flag.
00381 }
00382 procedure TZExpression.SetAutoVariables(Value: Boolean);
00383 begin
00384 FAutoVariables := Value;
00385 end;
00386
00387 {**
00388 Gets a list of default functions.
00389 @returns a list of default functions.
00390 }
00391 function TZExpression.GetDefaultFunctions: IZFunctionsList;
00392 begin
00393 Result := FDefaultFunctions;
00394 end;
00395
00396 {**
00397 Sets a new list of functions.
00398 @param Value a new list of functions.
00399 }
00400 procedure TZExpression.SetDefaultFunctions(Value: IZFunctionsList);
00401 begin
00402 FDefaultFunctions := Value;
00403 end;
00404
00405 {**
00406 Gets a list of default variables.
00407 @returns a list of default variables.
00408 }
00409 function TZExpression.GetDefaultVariables: IZVariablesList;
00410 begin
00411 Result := FDefaultVariables;
00412 end;
00413
00414 {**
00415 Sets a new list of variables.
00416 @param Value a new list of variables.
00417 }
00418 procedure TZExpression.SetDefaultVariables(Value: IZVariablesList);
00419 begin
00420 FDefaultVariables := Value;
00421 end;
00422
00423 {**
00424 Gets the current set expression string.
00425 @returns the current expression string.
00426 }
00427 function TZExpression.GetExpression: string;
00428 begin
00429 Result := TZExpressionParser(FParser).Expression;
00430 end;
00431
00432 {**
00433 Sets a new expression string.
00434 @param Value a new expression string.
00435 }
00436 procedure TZExpression.SetExpression(const Value: string);
00437 begin
00438 TZExpressionParser(FParser).Expression := Value;
00439 if FAutoVariables then
00440 CreateVariables(FDefaultVariables);
00441 end;
00442
00443 {**
00444 Gets a reference to the current variant manager.
00445 @returns a reference to the current variant manager.
00446 }
00447 function TZExpression.GetVariantManager: IZVariantManager;
00448 begin
00449 Result := FVariantManager;
00450 end;
00451
00452 {**
00453 Sets a new variant manager.
00454 @param Value a new variant manager.
00455 }
00456 procedure TZExpression.SetVariantManager(Value: IZVariantManager);
00457 begin
00458 FVariantManager := Value;
00459 end;
00460
00461 {**
00462 Gets the current expression tokenizer.
00463 @returns the current expression tokenizer.
00464 }
00465 function TZExpression.GetTokenizer: IZTokenizer;
00466 begin
00467 Result := FTokenizer;
00468 end;
00469
00470 {**
00471 Sets a new expression tokenizer.
00472 @param Value a new expression tokenizer.
00473 }
00474 procedure TZExpression.SetTokenizer(Value: IZTokenizer);
00475 begin
00476 FTokenizer := Value;
00477 TZExpressionParser(FParser).Tokenizer := Value;
00478 end;
00479
00480 {**
00481 Clears this class from all data.
00482 }
00483 procedure TZExpression.Clear;
00484 begin
00485 TZExpressionParser(FParser).Clear;
00486 FDefaultVariables.Clear;
00487 end;
00488
00489 {**
00490 Creates an empty variables.
00491 @param Variables a list of variables.
00492 }
00493 procedure TZExpression.CreateVariables(Variables: IZVariablesList);
00494 var
00495 I: Integer;
00496 Parser: TZExpressionParser;
00497 Name: string;
00498 begin
00499 Parser := TZExpressionParser(FParser);
00500 for I := 0 to Parser.Variables.Count - 1 do
00501 begin
00502 Name := Parser.Variables[I];
00503 if Variables.FindByName(Name) < 0 then
00504 Variables.Add(Name, NullVariant);
00505 end;
00506 end;
00507
00508 {**
00509 Evaluates this expression.
00510 @returns an evaluated expression value.
00511 }
00512 function TZExpression.Evaluate: TZVariant;
00513 begin
00514 Result := Evaluate3(FDefaultVariables, FDefaultFunctions);
00515 end;
00516
00517 {**
00518 Evaluates this expression.
00519 @param Variables a list of variables.
00520 @returns an evaluated expression value.
00521 }
00522 function TZExpression.Evaluate2(Variables: IZVariablesList): TZVariant;
00523 begin
00524 Result := Evaluate3(Variables, FDefaultFunctions);
00525 end;
00526
00527 {**
00528 Evaluates this expression.
00529 @param Variables a list of variables.
00530 @param Functions a list of functions.
00531 @returns an evaluated expression value.
00532 }
00533 function TZExpression.Evaluate3(Variables: IZVariablesList;
00534 Functions: IZFunctionsList): TZVariant;
00535 var
00536 Stack: TZExecutionStack;
00537 begin
00538 Stack := TZExecutionStack.Create;
00539 try
00540 Result := Evaluate4(Variables, Functions, Stack);
00541 finally
00542 Stack.Free;
00543 end;
00544 end;
00545
00546 {**
00547 Evaluates this expression.
00548 @param Variables a list of variables.
00549 @param Functions a list of functions.
00550 @param Stack an execution stack.
00551 @returns an evaluated expression value.
00552 }
00553 function TZExpression.Evaluate4(Variables: IZVariablesList;
00554 Functions: IZFunctionsList; Stack: TZExecutionStack): TZVariant;
00555 var
00556 I, Index, ParamsCount: Integer;
00557 Current: TZExpressionToken;
00558 Temp: string;
00559 Parser: TZExpressionParser;
00560 Value1, Value2: TZVariant;
00561 begin
00562 Parser := TZExpressionParser(FParser);
00563 Stack.Clear;
00564
00565 for I := 0 to Parser.ResultTokens.Count - 1 do
00566 begin
00567 Current := TZExpressionToken(Parser.ResultTokens[I]);
00568 case Current.TokenType of
00569 ttConstant:
00570 Stack.Push(Current.Value);
00571 ttVariable:
00572 begin
00573 Index := Variables.FindByName(DefVarManager.GetAsString(Current.Value));
00574 if Index < 0 then
00575 begin
00576 Temp := DefVarManager.GetAsString(Current.Value);
00577 raise TZExpressionError.Create(
00578 Format(SVariableWasNotFound, [Temp]));
00579 end;
00580 Stack.Push(Variables.Values[Index]);
00581 end;
00582 ttFunction:
00583 begin
00584 Index := Functions.FindByName(DefVarManager.GetAsString(Current.Value));
00585 if Index < 0 then
00586 begin
00587 Temp := DefVarManager.GetAsString(Current.Value);
00588 raise TZExpressionError.Create(
00589 Format(SFunctionWasNotFound, [Temp]));
00590 end;
00591 Value1 := Functions.Functions[Index].Execute(Stack,
00592 FVariantManager);
00593 ParamsCount := DefVarManager.GetAsInteger(Stack.Pop);
00594 while ParamsCount > 0 do
00595 begin
00596 Stack.Pop;
00597 Dec(ParamsCount);
00598 end;
00599 Stack.Push(Value1);
00600 end;
00601 ttAnd:
00602 begin
00603 Value2 := Stack.Pop;
00604 Value1 := Stack.Pop;
00605 Stack.Push(FVariantManager.OpAnd(Value1, Value2));
00606 end;
00607 ttOr:
00608 begin
00609 Value2 := Stack.Pop;
00610 Value1 := Stack.Pop;
00611 Stack.Push(FVariantManager.OpOr(Value1, Value2));
00612 end;
00613 ttXor:
00614 begin
00615 Value2 := Stack.Pop;
00616 Value1 := Stack.Pop;
00617 Stack.Push(FVariantManager.OpXor(Value1, Value2));
00618 end;
00619 ttNot:
00620 Stack.Push(FVariantManager.OpNot(Stack.Pop));
00621 ttPlus:
00622 begin
00623 Value2 := Stack.Pop;
00624 Value1 := Stack.Pop;
00625 Stack.Push(FVariantManager.OpAdd(Value1, Value2));
00626 end;
00627 ttMinus:
00628 begin
00629 Value2 := Stack.Pop;
00630 Value1 := Stack.Pop;
00631 Stack.Push(FVariantManager.OpSub(Value1, Value2));
00632 end;
00633 ttStar:
00634 begin
00635 Value2 := Stack.Pop;
00636 Value1 := Stack.Pop;
00637 Stack.Push(FVariantManager.OpMul(Value1, Value2));
00638 end;
00639 ttSlash:
00640 begin
00641 Value2 := Stack.Pop;
00642 Value1 := Stack.Pop;
00643 Stack.Push(FVariantManager.OpDiv(Value1, Value2));
00644 end;
00645 ttProcent:
00646 begin
00647 Value2 := Stack.Pop;
00648 Value1 := Stack.Pop;
00649 Stack.Push(FVariantManager.OpMod(Value1, Value2));
00650 end;
00651 ttEqual:
00652 begin
00653 Value2 := Stack.Pop;
00654 Value1 := Stack.Pop;
00655 Stack.Push(FVariantManager.OpEqual(Value1, Value2));
00656 end;
00657 ttNotEqual:
00658 begin
00659 Value2 := Stack.Pop;
00660 Value1 := Stack.Pop;
00661 Stack.Push(FVariantManager.OpNotEqual(Value1, Value2));
00662 end;
00663 ttMore:
00664 begin
00665 Value2 := Stack.Pop;
00666 Value1 := Stack.Pop;
00667 Stack.Push(FVariantManager.OpMore(Value1, Value2));
00668 end;
00669 ttLess:
00670 begin
00671 Value2 := Stack.Pop;
00672 Value1 := Stack.Pop;
00673 Stack.Push(FVariantManager.OpLess(Value1, Value2));
00674 end;
00675 ttEqualMore:
00676 begin
00677 Value2 := Stack.Pop;
00678 Value1 := Stack.Pop;
00679 Stack.Push(FVariantManager.OpMoreEqual(Value1, Value2));
00680 end;
00681 ttEqualLess:
00682 begin
00683 Value2 := Stack.Pop;
00684 Value1 := Stack.Pop;
00685 Stack.Push(FVariantManager.OpLessEqual(Value1, Value2));
00686 end;
00687 ttPower:
00688 begin
00689 Value2 := Stack.Pop;
00690 Value1 := Stack.Pop;
00691 Stack.Push(FVariantManager.OpPow(Value1, Value2));
00692 end;
00693 ttUnary:
00694 Stack.Push(FVariantManager.OpNegative(Stack.Pop));
00695 ttLike:
00696 begin
00697 Value2 := Stack.Pop;
00698 Value1 := Stack.Pop;
00699 FVariantManager.SetAsBoolean(Value1,
00700 IsMatch(FVariantManager.GetAsString(Value2),
00701 FVariantManager.GetAsString(Value1)));
00702 Stack.Push(Value1);
00703 end;
00704 ttNotLike:
00705 begin
00706 Value2 := Stack.Pop;
00707 Value1 := Stack.Pop;
00708 FVariantManager.SetAsBoolean(Value1,
00709 not IsMatch(FVariantManager.GetAsString(Value2),
00710 FVariantManager.GetAsString(Value1)));
00711 Stack.Push(Value1);
00712 end;
00713 ttIsNull:
00714 begin
00715 Value1 := Stack.Pop;
00716 FVariantManager.SetAsBoolean(Value1,
00717 FVariantManager.IsNull(Value1));
00718 Stack.Push(Value1);
00719 end;
00720 ttIsNotNull:
00721 begin
00722 Value1 := Stack.Pop;
00723 FVariantManager.SetAsBoolean(Value1,
00724 not FVariantManager.IsNull(Value1));
00725 Stack.Push(Value1);
00726 end;
00727 else
00728 raise TZExpressionError.Create(SInternalError);
00729 end;
00730 end;
00731
00732 if Stack.Count <> 1 then
00733 raise TZExpressionError.Create(SInternalError);
00734 Result := Stack.Pop;
00735 end;
00736
00737 end.