呵呵,你这么说我倒不好意思了,案例 FNSExprParser := TNSExprParser.Create; FNSExprParser.AddDataSet(dataset1.Name, dataset1, True);-- FNSExprParser.Clear; Result := FNSExprParser.GetExprValue( '条件字符串' );------------------------ TNSExprParser代码如下:------------unit ExprParser;{$T-,H+,X+,R-}interfaceuses Windows, Classes, DB, DBCommon, Variants;const NumericType = [ftSmallInt..ftDateTime, ftAutoInc, ftLargeint];type{ TFilterExpr } TExprToken = (etEnd, etSymbol, etName, etLiteral, etLParen, etRParen, etEQ, etNE, etGE, etLE, etGT, etLT, etADD, etSUB, etMUL, etDIV, etMod, etComma, etLIKE, etISNULL, etISNOTNULL, etIN); PExprNode = ^TExprNode; TExprNode = record FNext: PExprNode; FKind: TExprNodeKind; FPartial: Boolean; FOperator: TCANOperator; FData: Variant; FLeft: PExprNode; FRight: PExprNode; FDataType: TFieldType; FDataSize: Integer; FArgs: TList; FScopeKind: TExprScopeKind; FField: TField; IsNull: Boolean; end;{ TExprParser } TExprFuncEvent = procedure(FuncName: string; Params: OleVariant) of object; TAddFieldEvent = procedure(FieldName: string) of object; TNSExprParser = class private FSourcePtr: PChar; FTokenPtr: PChar; FTokenString: string; FStrTrue: string; FStrFalse: string; FToken: TExprToken; FPrevToken: TExprToken; FNumericLit: Boolean; FNodes: PExprNode; FDataSets: TStringList; FFuncList: TStringList; FOnRunFunc: TExprFuncEvent; FOnAddField: TAddFieldEvent; FDefaultDataSet: TDataSet; procedure NextToken; function NextTokenIsLParen: Boolean; function ParseExpr: PExprNode; function ParseExpr2: PExprNode; function ParseExpr3: PExprNode; function ParseExpr4: PExprNode; function ParseExpr5: PExprNode; function ParseExpr6: PExprNode; function ParseExpr7: PExprNode; function TokenName: string; function TokenSymbolIs(const S: string): Boolean; function TokenSymbolIsFunc(const S: string): Boolean; procedure TypeCheckArithOp(Node: PExprNode); procedure GetScopeKind(Root, Left, Right: PExprNode); procedure PutConstant(Node: PExprNode); function GetFieldByName(Name: string): TField; function NewNode(Kind: TExprNodeKind; Operator: TCANOperator; const Data: Variant; Left, Right: PExprNode): PExprNode; procedure PutExprNode(Node: PExprNode; ParentOp: TCANOperator); function OperatNode(Node: PExprNode): Variant; function GetFuncValue(Node: PExprNode): Variant; public constructor Create; destructor Destroy; override; procedure Clear; function SetExprParams(const Text: string): PExprNode; procedure AddDataSet(Name: string; DataSet: TDataSet; Default: Boolean = False); procedure DelDataSet(Name: string); procedure ClearDataSet; function GetNodeValue(Node: PExprNode): Variant; function GetExprValue(Text: string): Variant; property FuncList: TStringList read FFuncList; property FirstNode: PExprNode read FNodes; property OnRunFunc: TExprFuncEvent read FOnRunFunc write FOnRunFunc; property OnAddField: TAddFieldEvent read FOnAddField write FOnAddField; property DefaultDataSet: TDataSet read FDefaultDataSet write FDefaultDataSet; end;implementationuses SysUtils, DBConsts;const StringFieldTypes = [ftString, ftFixedChar, ftWideString, ftGuid]; BlobFieldTypes = [ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle, ftDBaseOle, ftTypedBinary, ftOraBlob, ftOraClob];procedure DecodeStr(Str: string; var Pre, Suf: string; SpChar: Char);var I: Integer;begin I := Pos(SpChar, Str); Pre := Copy(Str, 1, I - 1); Suf := Copy(Str, I + 1, Length(Str) - I);end;function IsNumeric(DataType: TFieldType): Boolean;begin Result := DataType in [ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency, ftBCD, ftAutoInc, ftLargeint];end;function IsTemporal(DataType: TFieldType): Boolean;begin Result := DataType in [ftDate, ftTime, ftDateTime];end;{ TNSFilterExpr }constructor TNSExprParser.Create;begin FStrTrue := STextTrue; FStrFalse := STextFalse; FDataSets := TStringList.Create; FDataSets.Sorted := True; FFuncList := TStringList.Create; FFuncList.Sorted := True; FNodes := nil;end;destructor TNSExprParser.Destroy;begin Clear; FDataSets.Free; FFuncList.Free;end;function TNSExprParser.SetExprParams(const Text: string): PExprNode;begin FSourcePtr := PChar(Text); NextToken; Result := ParseExpr; if FToken <> etEnd then DatabaseError('表达式错误'); if (Result^.FScopeKind = skAgg) then DatabaseError('表达式错误'); PutExprNode(Result, coNOTDEFINED);end;function TNSExprParser.NextTokenIsLParen: Boolean;var P: PChar;begin P := FSourcePtr; while (P^ <> #0) and (P^ <= ' ') do Inc(P); Result := P^ = '(';end;procedure TNSExprParser.NextToken;type ASet = set of Char;var P, TokenStart: PChar; L: Integer; StrBuf: array[0..255] of Char; function IsKatakana(const Chr: Byte): Boolean; begin Result := (SysLocale.PriLangID = LANG_JAPANESE) and (Chr in [$A1..$DF]); end; procedure Skip(TheSet: ASet); begin while TRUE do begin if P^ in LeadBytes then Inc(P, 2) else if (P^ in TheSet) or IsKatakana(Byte(P^)) then Inc(P) else Exit; end; end;begin FPrevToken := FToken; FTokenString := ''; P := FSourcePtr; while (P^ <> #0) and (P^ <= ' ') do Inc(P); if (P^ <> #0) and (P^ = '/') and (P[1] <> #0) and (P[1] = '*') then begin P := P + 2; while (P^ <> #0) and (P^ <> '*') do Inc(P); if (P^ = '*') and (P[1] <> #0) and (P[1] = '/') then P := P + 2 else DatabaseErrorFmt('错误字符', [P^]); end; while (P^ <> #0) and (P^ <= ' ') do Inc(P); FTokenPtr := P; case P^ of 'A'..'Z', 'a'..'z', '_', #$81..#$FE: begin TokenStart := P; if not SysLocale.FarEast then begin Inc(P); while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_', '.', '[', ']'] do Inc(P); end else Skip(['A'..'Z', 'a'..'z', '0'..'9', '_', '.', '[', ']']); SetString(FTokenString, TokenStart, P - TokenStart); FToken := etSymbol; if CompareText(FTokenString, 'LIKE') = 0 then { do not localize } FToken := etLIKE else if CompareText(FTokenString, 'IN') = 0 then { do not localize } FToken := etIN else if CompareText(FTokenString, 'IS') = 0 then { do not localize } begin while (P^ <> #0) and (P^ <= ' ') do Inc(P); TokenStart := P; Skip(['A'..'Z', 'a'..'z']); SetString(FTokenString, TokenStart, P - TokenStart); if CompareText(FTokenString, 'NOT') = 0 then { do not localize } begin while (P^ <> #0) and (P^ <= ' ') do Inc(P); TokenStart := P; Skip(['A'..'Z', 'a'..'z']); SetString(FTokenString, TokenStart, P - TokenStart); if CompareText(FTokenString, 'NULL') = 0 then FToken := etISNOTNULL else DatabaseError('错误关键字'); end else if CompareText(FTokenString, 'NULL') = 0 then { do not localize } begin FToken := etISNULL; end else DatabaseError('错误关键字'); end; end; '[': begin Inc(P); TokenStart := P; P := AnsiStrScan(P, ']'); if P = nil then DatabaseError('缺少结束标志]'); SetString(FTokenString, TokenStart, P - TokenStart); FToken := etName; Inc(P); end; '''': begin Inc(P); L := 0; while True do begin if P^ = #0 then DatabaseError('缺少字符串结束标志'); if P^ = '''' then begin Inc(P); if P^ <> '''' then Break; end; if L < SizeOf(StrBuf) then begin StrBuf[L] := P^; Inc(L); end; Inc(P); end; SetString(FTokenString, StrBuf, L); FToken := etLiteral; FNumericLit := False; end; '-', '0'..'9': begin if (FPrevToken <> etLiteral) and (FPrevToken <> etName) and (FPrevToken <> etSymbol) and (FPrevToken <> etRParen) then begin TokenStart := P; Inc(P); while (P^ in ['0'..'9', DecimalSeparator, 'e', 'E', '+', '-']) do Inc(P); if ((P - 1)^ = ',') and (DecimalSeparator = ',') and (P^ = ' ') then Dec(P); SetString(FTokenString, TokenStart, P - TokenStart); FToken := etLiteral; FNumericLit := True; end else begin FToken := etSUB; Inc(P); end; end; '(': begin Inc(P); FToken := etLParen; end; ')': begin Inc(P); FToken := etRParen; end; '<': begin Inc(P); case P^ of '=': begin Inc(P); FToken := etLE; end; '>': begin Inc(P); FToken := etNE; end; else FToken := etLT; end; end; '=': begin Inc(P); FToken := etEQ; end; '>': begin Inc(P); if P^ = '=' then begin Inc(P); FToken := etGE; end else FToken := etGT; end; '+': begin Inc(P); FToken := etADD; end; '*': begin Inc(P); FToken := etMUL; end; '/': begin Inc(P); FToken := etDIV; end; '%': begin Inc(P); FToken := etMod; end; ',': begin Inc(P); FToken := etComma; end; #0: FToken := etEnd; else DatabaseErrorFmt('错误的字符', [P^]); end; FSourcePtr := P;end;function TNSExprParser.ParseExpr: PExprNode;begin Result := ParseExpr2; while TokenSymbolIs('OR') do begin NextToken; Result := NewNode(enOperator, coOR, Unassigned, Result, ParseExpr2); GetScopeKind(Result, Result^.FLeft, Result^.FRight); Result^.FDataType := ftBoolean; end;end;function TNSExprParser.ParseExpr2: PExprNode;begin Result := ParseExpr3; while TokenSymbolIs('AND') do begin NextToken; Result := NewNode(enOperator, coAND, Unassigned, Result, ParseExpr3); GetScopeKind(Result, Result^.FLeft, Result^.FRight); Result^.FDataType := ftBoolean; end;end;function TNSExprParser.ParseExpr3: PExprNode;begin if TokenSymbolIs('NOT') then begin NextToken; Result := NewNode(enOperator, coNOT, Unassigned, ParseExpr4, nil); Result^.FDataType := ftBoolean; end else Result := ParseExpr4; GetScopeKind(Result, Result^.FLeft, Result^.FRight);end;function TNSExprParser.ParseExpr4: PExprNode;const Operators: array[etEQ..etLT] of TCANOperator = ( coEQ, coNE, coGE, coLE, coGT, coLT);var Operator: TCANOperator; Left, Right: PExprNode;begin Result := ParseExpr5; if (FToken in [etEQ..etLT]) or (FToken = etLIKE) or (FToken = etISNULL) or (FToken = etISNOTNULL) or (FToken = etIN) then begin case FToken of etEQ..etLT: Operator := Operators[FToken]; etLIKE: Operator := coLIKE; etISNULL: Operator := coISBLANK; etISNOTNULL: Operator := coNOTBLANK; etIN: Operator := coIN; else Operator := coNOTDEFINED; end; NextToken; Left := Result; if Operator = coIN then begin if FToken <> etLParen then DatabaseErrorFmt('期望的(被"%s"取代', [TokenName]); NextToken; Result := NewNode(enOperator, coIN, Unassigned, Left, nil); Result.FDataType := ftBoolean; if FToken <> etRParen then begin Result.FArgs := TList.Create; repeat Right := ParseExpr; if IsTemporal(Left.FDataType) then Right.FDataType := Left.FDataType; Result.FArgs.Add(Right); if (FToken <> etComma) and (FToken <> etRParen) then DatabaseErrorFmt('期望的)或,被"%s"取代', [TokenName]); if FToken = etComma then NextToken; until (FToken = etRParen) or (FToken = etEnd); if FToken <> etRParen then DatabaseErrorFmt('期望的)被"%s"取代', [TokenName]); NextToken; end else DatabaseError('In内容不能为空'); end else begin if (Operator <> coISBLANK) and (Operator <> coNOTBLANK) then Right := ParseExpr5 else Right := nil; Result := NewNode(enOperator, Operator, Unassigned, Left, Right); if Right <> nil then begin if (Left^.FKind = enField) and (Right^.FKind = enConst) then begin Right^.FDataType := Left^.FDataType; Right^.FDataSize := Left^.FDataSize; end else if (Right^.FKind = enField) and (Left^.FKind = enConst) then begin Left^.FDataType := Right^.FDataType; Left^.FDataSize := Right^.FDataSize; end; end; if (Left^.FDataType in BlobFieldTypes) and (Operator = coLIKE) then begin if Right^.FKind = enConst then Right^.FDataType := ftString; end else if (Operator <> coISBLANK) and (Operator <> coNOTBLANK) and ((Left^.FDataType in (BlobFieldTypes + [ftBytes])) or ((Right <> nil) and (Right^.FDataType in (BlobFieldTypes + [ftBytes])))) then DatabaseError('类型匹配错'); Result.FDataType := ftBoolean; if Right <> nil then begin if IsTemporal(Left.FDataType) and (Right.FDataType in StringFieldTypes) then Right.FDataType := Left.FDataType else if IsTemporal(Right.FDataType) and (Left.FDataType in StringFieldTypes) then Left.FDataType := Right.FDataType; end; GetScopeKind(Result, Left, Right); end; end;end;function TNSExprParser.ParseExpr5: PExprNode;const Operators: array[etADD..etMod] of TCANOperator = ( coADD, coSUB, coMUL, coDIV, coMod);var Operator: TCANOperator; Left, Right: PExprNode;begin Result := ParseExpr6; while FToken in [etADD, etSUB] do begin Operator := Operators[FToken]; Left := Result; NextToken; Right := ParseExpr6; Result := NewNode(enOperator, Operator, Unassigned, Left, Right); TypeCheckArithOp(Result); GetScopeKind(Result, Left, Right); end;end;function TNSExprParser.ParseExpr6: PExprNode;const Operators: array[etADD..etMod] of TCANOperator = ( coADD, coSUB, coMUL, coDIV, coMod);var Operator: TCANOperator; Left, Right: PExprNode;begin Result := ParseExpr7; while FToken in [etMUL, etMod, etDIV] do begin Operator := Operators[FToken]; Left := Result; NextToken; Right := ParseExpr7; Result := NewNode(enOperator, Operator, Unassigned, Left, Right); TypeCheckArithOp(Result); GetScopeKind(Result, Left, Right); end;end;function TNSExprParser.ParseExpr7: PExprNode;var FuncName: string;begin case FToken of etSymbol: if NextTokenIsLParen and TokenSymbolIsFunc(FTokenString) then begin Funcname := FTokenString; NextToken; if FToken <> etLParen then DatabaseErrorFmt('期望的(被"%s"取代', [TokenName]); NextToken; if (CompareText(FuncName, 'count') = 0) and (FToken = etMUL) then begin FuncName := 'COUNT(*)'; NextToken; end; Result := NewNode(enFunc, coNOTDEFINED, FuncName, nil, nil); if FToken <> etRParen then begin Result.FArgs := TList.Create; repeat Result.FArgs.Add(ParseExpr); if (FToken <> etComma) and (FToken <> etRParen) then DatabaseErrorFmt('期望的)或,被"%s"取代', [TokenName]); if FToken = etComma then NextToken; until (FToken = etRParen) or (FToken = etEnd); end else Result.FArgs := nil; end else if TokenSymbolIs('NULL') then begin Result := NewNode(enConst, coNOTDEFINED, Null, nil, nil); Result.FScopeKind := skConst; end else if TokenSymbolIs(FStrTrue) then begin Result := NewNode(enConst, coNOTDEFINED, 1, nil, nil); Result.FScopeKind := skConst; end else if TokenSymbolIs(FStrFalse) then begin Result := NewNode(enConst, coNOTDEFINED, 0, nil, nil); Result.FScopeKind := skConst; end else begin Result := NewNode(enField, coNOTDEFINED, FTokenString, nil, nil); Result.FScopeKind := skField; end; etName: begin Result := NewNode(enField, coNOTDEFINED, FTokenString, nil, nil); Result.FScopeKind := skField; end; etLiteral: begin Result := NewNode(enConst, coNOTDEFINED, FTokenString, nil, nil); if FNumericLit then Result^.FDataType := ftFloat else Result^.FDataType := ftString; Result.FScopeKind := skConst; end; etLParen: begin NextToken; Result := ParseExpr; if FToken <> etRParen then DatabaseErrorFmt('期望的)被"%s"取代', [TokenName]); end; else DatabaseErrorFmt('期望的表达式被"%s"取代', [TokenName]); Result := nil; end; NextToken;end;procedure TNSExprParser.GetScopeKind(Root, Left, Right: PExprNode);begin if (Left = nil) and (Right = nil) then Exit; if Right = nil then begin Root.FScopeKind := Left.FScopeKind; Exit; end; if ((Left^.FScopeKind = skField) and (Right^.FScopeKind = skAgg)) or ((Left^.FScopeKind = skAgg) and (Right^.FScopeKind = skField)) then DatabaseError('类型错误'); if (Left^.FScopeKind = skConst) and (Right^.FScopeKind = skConst) then Root^.FScopeKind := skConst else if (Left^.FScopeKind = skAgg) or (Right^.FScopeKind = skAgg) then Root^.FScopeKind := skAgg else if (Left^.FScopeKind = skField) or (Right^.FScopeKind = skField) then Root^.FScopeKind := skField;end;function TNSExprParser.TokenName: string;begin if FSourcePtr = FTokenPtr then Result := SExprNothing else begin SetString(Result, FTokenPtr, FSourcePtr - FTokenPtr); Result := '''' + Result + ''''; end;end;function TNSExprParser.TokenSymbolIs(const S: string): Boolean;begin Result := (FToken = etSymbol) and (CompareText(FTokenString, S) = 0);end;function TNSExprParser.TokenSymbolIsFunc(const S: string): Boolean;begin Result := FFuncList.IndexOf(S) >= 0;end;procedure TNSExprParser.TypeCheckArithOp(Node: PExprNode);begin with Node^ do begin if IsNumeric(FLeft.FDataType) and IsNumeric(FRight.FDataType) then FDataType := ftFloat else if (FLeft.FDataType in StringFieldTypes) and (FRight.FDataType in StringFieldTypes) and (FOperator = coADD) then FDataType := ftString else if IsTemporal(FLeft.FDataType) and IsNumeric(FRight.FDataType) and (FOperator = coADD) then FDataType := ftDateTime else if IsTemporal(FLeft.FDataType) and IsNumeric(FRight.FDataType) and (FOperator = coSUB) then FDataType := FLeft.FDataType else if IsTemporal(FLeft.FDataType) and IsTemporal(FRight.FDataType) and (FOperator = coSUB) then FDataType := ftFloat else if (FLeft.FDataType in StringFieldTypes) and IsTemporal(FRight.FDataType) and (FOperator = coSUB) then begin FLeft.FDataType := FRight.FDataType; FDataType := ftFloat; end else if (FLeft.FDataType in StringFieldTypes) and IsNumeric(FRight.FDataType) and (FLeft.FKind = enConst) then FLeft.FDataType := ftDateTime else DatabaseError('类型匹配错误'); end;end;function TNSExprParser.GetFieldByName(Name: string): TField;var I: Integer; S1, S2: string; DataSet: TDataSet;begin Result := nil; if (FDataSets.Count <= 0) and (FDefaultDataSet = nil) then Exit; DecodeStr(Name, S1, S2, '.'); DataSet := nil; if S1 = '' then DataSet := FDefaultDataSet else begin I := FDataSets.IndexOf(S1); if I >= 0 then DataSet := TDataSet(FDataSets.Objects); end; if (DataSet <> nil) and DataSet.Active then Result := DataSet.FindField(S2); if (DataSet <> nil) and DataSet.Active and (Result = nil) then DatabaseErrorFmt('字段%s不存在', [Name]); if Assigned(FOnAddField) then FOnAddField(Name);end;procedure TNSExprParser.PutConstant(Node: PExprNode);begin case Node^.FDataType of ftSmallInt, ftInteger, ftWord, ftAutoInc: if VarType(Node^.FData) = varString then Node^.FData := StrToInt(string(TVarData(Node^.FData).VString)); ftFloat, ftCurrency: if VarType(Node^.FData) = varString then Node^.FData := StrToFloat(string(TVarData(Node^.FData).VString)); ftDate: if VarType(Node^.FData) = varString then Node^.FData := StrToDate(string(TVarData(Node^.FData).VString)); ftTime: if VarType(Node^.FData) = varString then Node^.FData := StrToTime(string(TVarData(Node^.FData).VString)); ftDateTime: if VarType(Node^.FData) = varString then Node^.FData := StrToDateTime(string(TVarData(Node^.FData).VString)); ftBCD: if VarType(Node^.FData) = varString then Node^.FData := StrToCurr(string(TVarData(Node^.FData).VString)); end;end;procedure TNSExprParser.Clear;var Node: PExprNode;begin while FNodes <> nil do begin Node := FNodes; FNodes := Node^.FNext; if (Node^.FKind = enFunc) and (Node^.FArgs <> nil) then Node^.FArgs.Free; Dispose(Node); end;end;function TNSExprParser.NewNode(Kind: TExprNodeKind; Operator: TCANOperator; const Data: Variant; Left, Right: PExprNode): PExprNode;begin New(Result); FillChar(Result^, SizeOf(TExprNode), 0); with Result^ do begin FNext := FNodes; FKind := Kind; FPartial := False; FOperator := Operator; FData := Data; FLeft := Left; FRight := Right; end; FNodes := Result; if Kind = enField then begin Result.FField := GetFieldByName(Data); if Result.FField <> nil then begin Result^.FDataType := Result.FField.DataType; Result^.FDataSize := Result.FField.Size; end; end;end;procedure TNSExprParser.PutExprNode(Node: PExprNode; ParentOp: TCANOperator);const ReverseOperator: array[coEQ..coLE] of TCANOperator = (coEQ, coNE, coLT, coGT, coLE, coGE); BoolFalse: WordBool = False;var I: Integer; Left, Right, Temp: PExprNode; Operator: TCANOperator; CaseInsensitive, PartialLength, L: Integer; S: string; Dealed: Boolean;begin case Node^.FKind of enConst: PutConstant(Node); enFunc: if Node^.FArgs <> nil then for I := 0 to Node^.FArgs.Count - 1 do PutExprNode(Node^.FArgs.Items, Node^.FOperator); enOperator: case Node^.FOperator of coIN: begin PutExprNode(Node^.FLeft, Node^.FOperator); for I := 0 to Node^.FArgs.Count - 1 do PutExprNode(Node^.FArgs.Items, Node^.FOperator); end; coNOT, coISBLANK, coNOTBLANK: PutExprNode(Node^.FLeft, Node^.FOperator); coEQ..coLE, coAND, coOR, coADD..coDIV, coLIKE, coASSIGN: begin Operator := Node^.FOperator; Left := Node^.FLeft; Right := Node^.FRight; if (Operator in [coEQ..coLE]) and (Right^.FKind = enField) and (Left^.FKind <> enField) then begin Temp := Left; Left := Right; Right := Temp; Operator := ReverseOperator[Operator]; end; Dealed := False; if (Left^.FKind = enField) and (Right^.FKind = enConst) and ((Node^.FOperator = coEQ) or (Node^.FOperator = coNE) or (Node^.FOperator = coLIKE)) then begin if VarIsNull(Right^.FData) then begin case Node^.FOperator of coEQ: Operator := coISBLANK; coNE: Operator := coNOTBLANK; else DatabaseError('不可定义为空'); end; PutExprNode(Left, Node^.FOperator); Dealed := True; end else if (Right^.FDataType in StringFieldTypes) then begin S := Right^.FData; L := Length(S); if L <> 0 then begin CaseInsensitive := 0; PartialLength := 0; if Node^.FPartial then PartialLength := L else if (L > 1) and (S[L] = '*') then begin Delete(S, L, 1); PartialLength := L - 1; end; if (CaseInsensitive <> 0) or (PartialLength <> 0) then begin PutExprNode(Left, Node^.FOperator); Dealed := True; end; end; end; end; if not Dealed then begin if (Operator = coISBLANK) or (Operator = coNOTBLANK) then PutExprNode(Left, Node^.FOperator) else begin PutExprNode(Left, Node^.FOperator); PutExprNode(Right, Node^.FOperator); end; end; end; end; end;end;procedure TNSExprParser.AddDataSet(Name: string; DataSet: TDataSet; Default: Boolean = False);var I: Integer;begin I := FDataSets.IndexOf(Name); if I < 0 then FDataSets.AddObject(Name, DataSet) else FDataSets.Objects := DataSet; if Default then FDefaultDataSet := DataSet;end;function TNSExprParser.GetNodeValue(Node: PExprNode): Variant;begin Result := NULL; case Node.FKind of enField: if Node.FField <> nil then Result := Node.FField.Value; enConst: Result := Node.FData; enOperator: Result := OperatNode(Node); enFunc: Result := GetFuncValue(Node); end; if VarisNull(Result) then begin if Node.FDataType in NumericType then Result := 0 else Result := ''; Node.IsNull := True; end else Node.IsNull := False;end;function TNSExprParser.OperatNode(Node: PExprNode): Variant;var Left, Right: Variant;begin if Node.FLeft <> nil then Left := GetNodeValue(Node.FLeft) else Left := NULL; if Node.FRight <> nil then Right := GetNodeValue(Node.FRight) else Right := NULL; case Node.FOperator of coISBLANK: Result := Node.FLeft.IsNull; coNOTBLANK: Result := not Node.FLeft.IsNull; coEQ: Result := Left = Right; coNE: Result := Left <> Right; coGT: Result := Left > Right; coLT: Result := Left < Right; coGE: Result := Left >= Right; coLE: Result := Left <= Right; coNOT: Result := not Left; coAND: Result := Left and Right; coOR: Result := Left or Right; coADD: Result := Left + Right; coSUB: Result := Left - Right; coMUL: Result := Left * Right; coDIV: if Right = 0 then Result := 0 else Result := Left / Right; coMOD: if Right = 0 then Result := 0 else Result := Left mod Right; else Result := NULL; end;end;function TNSExprParser.GetFuncValue(Node: PExprNode): Variant;var I: Integer; Params: OleVariant;begin Result := Null; if Assigned(FOnRunFunc) then begin Params := Null; if (Node.FArgs <> nil) and (Node.FArgs.Count > 0) then begin Params := VarArrayCreate(Node.FArgs.Count, varVariant); for I := 0 to Node.FArgs.Count - 1 do Params := GetNodeValue(Node.FArgs); end; FOnRunFunc(VartoStr(Node.FData), Params); end;end;function TNSExprParser.GetExprValue(Text: string): Variant;var Node: PExprNode;begin Clear; Node := SetExprParams(Text); Result := GetNodeValue(Node);end;procedure TNSExprParser.DelDataSet(Name: string);var I: Integer;begin I := FDataSets.IndexOf(Name); if I >= 0 then FDataSets.Delete(I);end;procedure TNSExprParser.ClearDataSet;begin FDataSets.Clear;end;end.