You've already forked lazarus-ccr
fpspreadsheet: Modify expression parser to accept decimal and list separators different from the default point and comma.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3509 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -41,7 +41,7 @@ begin
|
|||||||
//cell := Worksheet.WriteFormula(1, 0, 'Day(Date(2014, 1, 12))');
|
//cell := Worksheet.WriteFormula(1, 0, 'Day(Date(2014, 1, 12))');
|
||||||
//cell := Worksheet.WriteFormula(1, 0, 'SUM(1,2,3)');
|
//cell := Worksheet.WriteFormula(1, 0, 'SUM(1,2,3)');
|
||||||
//cell := Worksheet.WriteFormula(1, 0, 'CELL("address",A1)');
|
//cell := Worksheet.WriteFormula(1, 0, 'CELL("address",A1)');
|
||||||
cell := Worksheet.WriteFormula(1, 0, 'ISBLANK(A1)');
|
cell := Worksheet.WriteFormula(1, 0, 'SUM(A1, 1.2, 1.3)');
|
||||||
|
|
||||||
WriteLn('A1: ', worksheet.ReadAsUTF8Text(0, 0));
|
WriteLn('A1: ', worksheet.ReadAsUTF8Text(0, 0));
|
||||||
WriteLn('B1: ', worksheet.ReadAsUTF8Text(0, 1));
|
WriteLn('B1: ', worksheet.ReadAsUTF8Text(0, 1));
|
||||||
@ -64,7 +64,8 @@ begin
|
|||||||
rtError : WriteLn(GetErrorValueStr(res.ResError));
|
rtError : WriteLn(GetErrorValueStr(res.ResError));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
WriteLn('Reconstructed string formula: ', parser.BuildStringFormula);
|
WriteLn('Reconstructed string formula: ', parser.Expression);
|
||||||
|
WriteLn('Reconstructed localized formula: ', parser.LocalizedExpression[DefaultFormatSettings]);
|
||||||
formula := parser.RPNFormula;
|
formula := parser.RPNFormula;
|
||||||
|
|
||||||
for i:=0 to Length(formula)-1 do begin
|
for i:=0 to Length(formula)-1 do begin
|
||||||
@ -93,7 +94,7 @@ begin
|
|||||||
try
|
try
|
||||||
try
|
try
|
||||||
parser.RPNFormula := formula;
|
parser.RPNFormula := formula;
|
||||||
s := parser.BuildStringFormula;
|
s := parser.Expression;
|
||||||
WriteLn('String formula, reconstructed from RPN formula: ', s);
|
WriteLn('String formula, reconstructed from RPN formula: ', s);
|
||||||
except on E:Exception do
|
except on E:Exception do
|
||||||
begin
|
begin
|
||||||
|
@ -67,7 +67,7 @@ type
|
|||||||
ttCell, ttCellRange, ttNumber, ttString, ttIdentifier,
|
ttCell, ttCellRange, ttNumber, ttString, ttIdentifier,
|
||||||
ttPlus, ttMinus, ttMul, ttDiv, ttConcat, ttPercent, ttPower, ttLeft, ttRight,
|
ttPlus, ttMinus, ttMul, ttDiv, ttConcat, ttPercent, ttPower, ttLeft, ttRight,
|
||||||
ttLessThan, ttLargerThan, ttEqual, ttNotEqual, ttLessThanEqual, ttLargerThanEqual,
|
ttLessThan, ttLargerThan, ttEqual, ttNotEqual, ttLessThanEqual, ttLargerThanEqual,
|
||||||
ttComma, ttTrue, ttFalse, ttEOF
|
ttListSep, ttTrue, ttFalse, ttEOF
|
||||||
);
|
);
|
||||||
|
|
||||||
TsExprFloat = Double;
|
TsExprFloat = Double;
|
||||||
@ -110,6 +110,8 @@ type
|
|||||||
|
|
||||||
{ TsExprNode }
|
{ TsExprNode }
|
||||||
TsExprNode = class(TObject)
|
TsExprNode = class(TObject)
|
||||||
|
private
|
||||||
|
FParser: TsExpressionParser;
|
||||||
protected
|
protected
|
||||||
procedure CheckNodeType(ANode: TsExprNode; Allowed: TsResultTypes);
|
procedure CheckNodeType(ANode: TsExprNode; Allowed: TsResultTypes);
|
||||||
// A procedure with var saves an implicit try/finally in each node
|
// A procedure with var saves an implicit try/finally in each node
|
||||||
@ -121,6 +123,7 @@ type
|
|||||||
procedure Check; virtual; abstract;
|
procedure Check; virtual; abstract;
|
||||||
function NodeType: TsResultType; virtual; abstract;
|
function NodeType: TsResultType; virtual; abstract;
|
||||||
function NodeValue: TsExpressionResult;
|
function NodeValue: TsExpressionResult;
|
||||||
|
property Parser: TsExpressionParser read FParser;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TsExprArgumentArray = array of TsExprNode;
|
TsExprArgumentArray = array of TsExprNode;
|
||||||
@ -133,7 +136,7 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure CheckSameNodeTypes; virtual;
|
procedure CheckSameNodeTypes; virtual;
|
||||||
public
|
public
|
||||||
constructor Create(ALeft, ARight: TsExprNode);
|
constructor Create(AParser: TsExpressionParser; ALeft, ARight: TsExprNode);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
property Left: TsExprNode read FLeft;
|
property Left: TsExprNode read FLeft;
|
||||||
@ -295,7 +298,7 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
public
|
public
|
||||||
constructor Create(AOperand: TsExprNode);
|
constructor Create(AParser: TsExpressionParser; AOperand: TsExprNode);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
property Operand: TsExprNode read FOperand;
|
property Operand: TsExprNode read FOperand;
|
||||||
end;
|
end;
|
||||||
@ -399,12 +402,12 @@ type
|
|||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
constructor CreateString(AValue: String);
|
constructor CreateString(AParser: TsExpressionParser; AValue: String);
|
||||||
constructor CreateInteger(AValue: Int64);
|
constructor CreateInteger(AParser: TsExpressionParser; AValue: Int64);
|
||||||
constructor CreateDateTime(AValue: TDateTime);
|
constructor CreateDateTime(AParser: TsExpressionParser; AValue: TDateTime);
|
||||||
constructor CreateFloat(AValue: TsExprFloat);
|
constructor CreateFloat(AParser: TsExpressionParser; AValue: TsExprFloat);
|
||||||
constructor CreateBoolean(AValue: Boolean);
|
constructor CreateBoolean(AParser: TsExpressionParser; AValue: Boolean);
|
||||||
constructor CreateError(AValue: TsErrorValue);
|
constructor CreateError(AParser: TsExpressionParser; AValue: TsErrorValue);
|
||||||
function AsString: string; override;
|
function AsString: string; override;
|
||||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||||
function NodeType : TsResultType; override;
|
function NodeType : TsResultType; override;
|
||||||
@ -451,6 +454,7 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure CheckResultType(const AType: TsResultType);
|
procedure CheckResultType(const AType: TsResultType);
|
||||||
procedure CheckVariable;
|
procedure CheckVariable;
|
||||||
|
function GetFormatSettings: TFormatSettings;
|
||||||
public
|
public
|
||||||
function ArgumentCount: Integer;
|
function ArgumentCount: Integer;
|
||||||
procedure Assign(Source: TPersistent); override;
|
procedure Assign(Source: TPersistent); override;
|
||||||
@ -533,7 +537,7 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
constructor CreateIdentifier(AID: TsExprIdentifierDef);
|
constructor CreateIdentifier(AParser: TsExpressionParser; AID: TsExprIdentifierDef);
|
||||||
function NodeType: TsResultType; override;
|
function NodeType: TsResultType; override;
|
||||||
property Identifier: TsExprIdentifierDef read FID;
|
property Identifier: TsExprIdentifierDef read FID;
|
||||||
end;
|
end;
|
||||||
@ -553,8 +557,8 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure CalcParams;
|
procedure CalcParams;
|
||||||
public
|
public
|
||||||
constructor CreateFunction(AID: TsExprIdentifierDef;
|
constructor CreateFunction(AParser: TsExpressionParser;
|
||||||
const Args: TsExprArgumentArray); virtual;
|
AID: TsExprIdentifierDef; const Args: TsExprArgumentArray); virtual;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||||
function AsString: String; override;
|
function AsString: String; override;
|
||||||
@ -570,8 +574,8 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
constructor CreateFunction(AID: TsExprIdentifierDef;
|
constructor CreateFunction(AParser: TsExpressionParser;
|
||||||
const Args: TsExprArgumentArray); override;
|
AID: TsExprIdentifierDef; const Args: TsExprArgumentArray); override;
|
||||||
property CallBack: TsExprFunctionCallBack read FCallBack;
|
property CallBack: TsExprFunctionCallBack read FCallBack;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -582,8 +586,8 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
constructor CreateFunction(AID: TsExprIdentifierDef;
|
constructor CreateFunction(AParser: TsExpressionParser;
|
||||||
const Args: TsExprArgumentArray); override;
|
AID: TsExprIdentifierDef; const Args: TsExprArgumentArray); override;
|
||||||
property CallBack: TsExprFunctionEvent read FCallBack;
|
property CallBack: TsExprFunctionEvent read FCallBack;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -599,9 +603,10 @@ type
|
|||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
constructor Create(AWorksheet: TsWorksheet; ACellString: String); overload;
|
constructor Create(AParser: TsExpressionParser; AWorksheet: TsWorksheet;
|
||||||
constructor Create(AWorksheet: TsWorksheet; ARow, ACol: Cardinal;
|
ACellString: String); overload;
|
||||||
AFlags: TsRelFlags); overload;
|
constructor Create(AParser: TsExpressionParser; AWorksheet: TsWorksheet;
|
||||||
|
ARow, ACol: Cardinal; AFlags: TsRelFlags); overload;
|
||||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||||
function AsString: string; override;
|
function AsString: string; override;
|
||||||
function NodeType: TsResultType; override;
|
function NodeType: TsResultType; override;
|
||||||
@ -619,9 +624,10 @@ type
|
|||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
procedure GetNodeValue(var Result: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
constructor Create(AWorksheet: TsWorksheet; ACellRangeString: String); overload;
|
constructor Create(AParser: TsExpressionParser; AWorksheet: TsWorksheet;
|
||||||
constructor Create(AWorksheet: TsWorksheet; ARow1,ACol1, ARow2,ACol2: Cardinal;
|
ACellRangeString: String); overload;
|
||||||
AFlags: TsRelFlags); overload;
|
constructor Create(AParser: TsExpressionParser; AWorksheet: TsWorksheet;
|
||||||
|
ARow1,ACol1, ARow2,ACol2: Cardinal; AFlags: TsRelFlags); overload;
|
||||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||||
function AsString: String; override;
|
function AsString: String; override;
|
||||||
function NodeType: TsResultType; override;
|
function NodeType: TsResultType; override;
|
||||||
@ -637,6 +643,7 @@ type
|
|||||||
FToken: String;
|
FToken: String;
|
||||||
FTokenType: TsTokenType;
|
FTokenType: TsTokenType;
|
||||||
private
|
private
|
||||||
|
FParser: TsExpressionParser;
|
||||||
function GetCurrentChar: Char;
|
function GetCurrentChar: Char;
|
||||||
procedure ScanError(Msg: String);
|
procedure ScanError(Msg: String);
|
||||||
protected
|
protected
|
||||||
@ -652,7 +659,7 @@ type
|
|||||||
function IsDigit(C: Char): Boolean; // inline;
|
function IsDigit(C: Char): Boolean; // inline;
|
||||||
function IsAlpha(C: Char): Boolean; // inline;
|
function IsAlpha(C: Char): Boolean; // inline;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create(AParser: TsExpressionParser);
|
||||||
function GetToken: TsTokenType;
|
function GetToken: TsTokenType;
|
||||||
property Token: String read FToken;
|
property Token: String read FToken;
|
||||||
property TokenType: TsTokenType read FTokenType;
|
property TokenType: TsTokenType read FTokenType;
|
||||||
@ -689,9 +696,15 @@ type
|
|||||||
procedure SetRPNFormula(const AFormula: TsRPNFormula);
|
procedure SetRPNFormula(const AFormula: TsRPNFormula);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
FFormatSettings: TFormatSettings;
|
||||||
class function BuiltinExpressionManager: TsBuiltInExpressionManager;
|
class function BuiltinExpressionManager: TsBuiltInExpressionManager;
|
||||||
|
function BuildStringFormula(AFormatSettings: TFormatSettings): String;
|
||||||
procedure ParserError(Msg: String);
|
procedure ParserError(Msg: String);
|
||||||
procedure SetExpression(const AValue: String); virtual;
|
function GetExpression: String;
|
||||||
|
function GetLocalizedExpression(const AFormatSettings: TFormatSettings): String; virtual;
|
||||||
|
procedure SetExpression(const AValue: String);
|
||||||
|
procedure SetLocalizedExpression(const AFormatSettings: TFormatSettings;
|
||||||
|
const AValue: String); virtual;
|
||||||
procedure CheckResultType(const Res: TsExpressionResult;
|
procedure CheckResultType(const Res: TsExpressionResult;
|
||||||
AType: TsResultType); inline;
|
AType: TsResultType); inline;
|
||||||
function CurrentToken: String;
|
function CurrentToken: String;
|
||||||
@ -714,7 +727,6 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function IdentifierByName(AName: ShortString): TsExprIdentifierDef; virtual;
|
function IdentifierByName(AName: ShortString): TsExprIdentifierDef; virtual;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
function BuildStringFormula: String;
|
|
||||||
function Evaluate: TsExpressionResult;
|
function Evaluate: TsExpressionResult;
|
||||||
procedure EvaluateExpression(var Result: TsExpressionResult);
|
procedure EvaluateExpression(var Result: TsExpressionResult);
|
||||||
function ResultType: TsResultType;
|
function ResultType: TsResultType;
|
||||||
@ -724,7 +736,9 @@ type
|
|||||||
property AsBoolean: Boolean read GetAsBoolean;
|
property AsBoolean: Boolean read GetAsBoolean;
|
||||||
property AsDateTime: TDateTime read GetAsDateTime;
|
property AsDateTime: TDateTime read GetAsDateTime;
|
||||||
// The expression to parse
|
// The expression to parse
|
||||||
property Expression: String read FExpression write SetExpression;
|
property Expression: String read GetExpression write SetExpression;
|
||||||
|
property LocalizedExpression[AFormatSettings: TFormatSettings]: String
|
||||||
|
read GetLocalizedExpression write SetLocalizedExpression;
|
||||||
property RPNFormula: TsRPNFormula read GetRPNFormula write SetRPNFormula;
|
property RPNFormula: TsRPNFormula read GetRPNFormula write SetRPNFormula;
|
||||||
property Identifiers: TsExprIdentifierDefs read FIdentifiers write SetIdentifiers;
|
property Identifiers: TsExprIdentifierDefs read FIdentifiers write SetIdentifiers;
|
||||||
property BuiltIns: TsBuiltInExprCategories read FBuiltIns write SetBuiltIns;
|
property BuiltIns: TsBuiltInExprCategories read FBuiltIns write SetBuiltIns;
|
||||||
@ -805,7 +819,8 @@ const
|
|||||||
bcInfo, bcUser];
|
bcInfo, bcUser];
|
||||||
|
|
||||||
var
|
var
|
||||||
ExprFormatSettings: TFormatSettings;
|
ExprFormatSettings: TFormatSettings; // MUST BE REMOVED
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -816,10 +831,10 @@ const
|
|||||||
cNull = #0;
|
cNull = #0;
|
||||||
cDoubleQuote = '"';
|
cDoubleQuote = '"';
|
||||||
|
|
||||||
Digits = ['0'..'9', '.'];
|
Digits = ['0'..'9']; // + decimalseparator
|
||||||
WhiteSpace = [' ', #13, #10, #9];
|
WhiteSpace = [' ', #13, #10, #9];
|
||||||
Operators = ['+', '-', '<', '>', '=', '/', '*', '&', '%', '^'];
|
Operators = ['+', '-', '<', '>', '=', '/', '*', '&', '%', '^'];
|
||||||
Delimiters = Operators + [',', '(', ')'];
|
Delimiters = Operators + ['(', ')']; // + listseparator
|
||||||
Symbols = Delimiters;
|
Symbols = Delimiters;
|
||||||
WordDelimiters = WhiteSpace + Symbols;
|
WordDelimiters = WhiteSpace + Symbols;
|
||||||
|
|
||||||
@ -921,9 +936,10 @@ end;
|
|||||||
{ TsExpressionScanner }
|
{ TsExpressionScanner }
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
|
|
||||||
constructor TsExpressionScanner.Create;
|
constructor TsExpressionScanner.Create(AParser: TsExpressionParser);
|
||||||
begin
|
begin
|
||||||
Source := '';
|
Source := '';
|
||||||
|
FParser := AParser;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionScanner.DoDelimiter: TsTokenType;
|
function TsExpressionScanner.DoDelimiter: TsTokenType;
|
||||||
@ -948,6 +964,9 @@ begin
|
|||||||
else
|
else
|
||||||
Result := ttLessThanEqual;
|
Result := ttLessThanEqual;
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
if D = FParser.FFormatSettings.ListSeparator then
|
||||||
|
Result := ttListSep
|
||||||
else
|
else
|
||||||
case D of
|
case D of
|
||||||
'+' : Result := ttPlus;
|
'+' : Result := ttPlus;
|
||||||
@ -962,7 +981,7 @@ begin
|
|||||||
'=' : Result := ttEqual;
|
'=' : Result := ttEqual;
|
||||||
'(' : Result := ttLeft;
|
'(' : Result := ttLeft;
|
||||||
')' : Result := ttRight;
|
')' : Result := ttRight;
|
||||||
',' : Result := ttComma;
|
// ',' : Result := ttComma;
|
||||||
else
|
else
|
||||||
ScanError(Format(SUnknownDelimiter, [D]));
|
ScanError(Format(SUnknownDelimiter, [D]));
|
||||||
end;
|
end;
|
||||||
@ -1015,7 +1034,7 @@ begin
|
|||||||
prevC := Upcase(C);
|
prevC := Upcase(C);
|
||||||
C := NextPos;
|
C := NextPos;
|
||||||
end;
|
end;
|
||||||
if not TryStrToFloat(FToken, X, ExprFormatSettings) then
|
if not TryStrToFloat(FToken, X, FParser.FFormatSettings) then
|
||||||
ScanError(Format(SErrInvalidNumber, [FToken]));
|
ScanError(Format(SErrInvalidNumber, [FToken]));
|
||||||
Result := ttNumber;
|
Result := ttNumber;
|
||||||
end;
|
end;
|
||||||
@ -1085,17 +1104,17 @@ end;
|
|||||||
|
|
||||||
function TsExpressionScanner.IsDelim(C: Char): Boolean;
|
function TsExpressionScanner.IsDelim(C: Char): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := C in Delimiters;
|
Result := (C in Delimiters) or (C = FParser.FFormatSettings.ListSeparator);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionScanner.IsDigit(C: Char): Boolean;
|
function TsExpressionScanner.IsDigit(C: Char): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := C in Digits;
|
Result := (C in Digits) or (C = FParser.FFormatSettings.DecimalSeparator);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionScanner.IsWordDelim(C: Char): Boolean;
|
function TsExpressionScanner.IsWordDelim(C: Char): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := C in WordDelimiters;
|
Result := (C in WordDelimiters) or (C = FParser.FFormatSettings.ListSeparator);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionScanner.NextPos: Char;
|
function TsExpressionScanner.NextPos: Char;
|
||||||
@ -1140,7 +1159,7 @@ begin
|
|||||||
FWorksheet := AWorksheet;
|
FWorksheet := AWorksheet;
|
||||||
FIdentifiers := TsExprIdentifierDefs.Create(TsExprIdentifierDef);
|
FIdentifiers := TsExprIdentifierDefs.Create(TsExprIdentifierDef);
|
||||||
FIdentifiers.FParser := Self;
|
FIdentifiers.FParser := Self;
|
||||||
FScanner := TsExpressionScanner.Create;
|
FScanner := TsExpressionScanner.Create(self);
|
||||||
FHashList := TFPHashObjectList.Create(False);
|
FHashList := TFPHashObjectList.Create(False);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1153,12 +1172,17 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionParser.BuildStringFormula: String;
|
{ Constructs the string formula from the tree of expression nodes. Gets the
|
||||||
|
decimal and list separator from the formatsettings provided. }
|
||||||
|
function TsExpressionParser.BuildStringFormula(AFormatSettings: TFormatSettings): String;
|
||||||
begin
|
begin
|
||||||
if FExprNode = nil then
|
if FExprNode = nil then
|
||||||
Result := ''
|
Result := ''
|
||||||
else
|
else
|
||||||
|
begin
|
||||||
|
FFormatSettings := AFormatSettings;
|
||||||
Result := FExprNode.AsString;
|
Result := FExprNode.AsString;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TsExpressionParser.BuiltinExpressionManager: TsBuiltInExpressionManager;
|
class function TsExpressionParser.BuiltinExpressionManager: TsBuiltInExpressionManager;
|
||||||
@ -1200,12 +1224,12 @@ begin
|
|||||||
case ToDo.NodeType of
|
case ToDo.NodeType of
|
||||||
rtInteger :
|
rtInteger :
|
||||||
case ToType of
|
case ToType of
|
||||||
rtFloat : Result := TsIntToFloatExprNode.Create(Result);
|
rtFloat : Result := TsIntToFloatExprNode.Create(self, Result);
|
||||||
rtDateTime : Result := TsIntToDateTimeExprNode.Create(Result);
|
rtDateTime : Result := TsIntToDateTimeExprNode.Create(self, Result);
|
||||||
end;
|
end;
|
||||||
rtFloat :
|
rtFloat :
|
||||||
case ToType of
|
case ToType of
|
||||||
rtDateTime : Result := TsFloatToDateTimeExprNode.Create(Result);
|
rtDateTime : Result := TsFloatToDateTimeExprNode.Create(self, Result);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1404,7 +1428,7 @@ begin
|
|||||||
else
|
else
|
||||||
ParserError(SErrUnknownComparison)
|
ParserError(SErrUnknownComparison)
|
||||||
end;
|
end;
|
||||||
Result := C.Create(Result, right);
|
Result := C.Create(self, Result, right);
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
Result.Free;
|
Result.Free;
|
||||||
@ -1427,9 +1451,9 @@ begin
|
|||||||
right := Level4;
|
right := Level4;
|
||||||
CheckNodes(Result, right);
|
CheckNodes(Result, right);
|
||||||
case tt of
|
case tt of
|
||||||
ttPlus : Result := TsAddExprNode.Create(Result, right);
|
ttPlus : Result := TsAddExprNode.Create(self, Result, right);
|
||||||
ttMinus : Result := TsSubtractExprNode.Create(Result, right);
|
ttMinus : Result := TsSubtractExprNode.Create(self, Result, right);
|
||||||
ttConcat: Result := TsConcatExprNode.Create(Result, right);
|
ttConcat: Result := TsConcatExprNode.Create(self, Result, right);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
@ -1453,8 +1477,8 @@ begin
|
|||||||
right := Level5;
|
right := Level5;
|
||||||
CheckNodes(Result, right);
|
CheckNodes(Result, right);
|
||||||
case tt of
|
case tt of
|
||||||
ttMul : Result := TsMultiplyExprNode.Create(Result, right);
|
ttMul : Result := TsMultiplyExprNode.Create(self, Result, right);
|
||||||
ttDiv : Result := TsDivideExprNode.Create(Result, right);
|
ttDiv : Result := TsDivideExprNode.Create(self, Result, right);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
@ -1479,9 +1503,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
Result := Level6;
|
Result := Level6;
|
||||||
if isPlus then
|
if isPlus then
|
||||||
Result := TsUPlusExprNode.Create(Result);
|
Result := TsUPlusExprNode.Create(self, Result);
|
||||||
if isMinus then
|
if isMinus then
|
||||||
Result := TsUMinusExprNode.Create(Result);
|
Result := TsUMinusExprNode.Create(self, Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionParser.Level6: TsExprNode;
|
function TsExpressionParser.Level6: TsExprNode;
|
||||||
@ -1493,7 +1517,7 @@ begin
|
|||||||
if (TokenType = ttLeft) then
|
if (TokenType = ttLeft) then
|
||||||
begin
|
begin
|
||||||
GetToken;
|
GetToken;
|
||||||
Result := TsParenthesisExprNode.Create(Level1);
|
Result := TsParenthesisExprNode.Create(self, Level1);
|
||||||
try
|
try
|
||||||
if (TokenType <> ttRight) then
|
if (TokenType <> ttRight) then
|
||||||
ParserError(Format(SErrBracketExpected, [SCanner.Pos, CurrentToken]));
|
ParserError(Format(SErrBracketExpected, [SCanner.Pos, CurrentToken]));
|
||||||
@ -1514,7 +1538,7 @@ begin
|
|||||||
GetToken;
|
GetToken;
|
||||||
Right := Primitive;
|
Right := Primitive;
|
||||||
CheckNodes(Result, right);
|
CheckNodes(Result, right);
|
||||||
Result := TsPowerExprNode.Create(Result, Right);
|
Result := TsPowerExprNode.Create(self, Result, Right);
|
||||||
//GetToken;
|
//GetToken;
|
||||||
except
|
except
|
||||||
Result.Free;
|
Result.Free;
|
||||||
@ -1570,26 +1594,26 @@ begin
|
|||||||
if (TokenType = ttNumber) then
|
if (TokenType = ttNumber) then
|
||||||
begin
|
begin
|
||||||
if TryStrToInt64(CurrentToken, I) then
|
if TryStrToInt64(CurrentToken, I) then
|
||||||
Result := TsConstExprNode.CreateInteger(I)
|
Result := TsConstExprNode.CreateInteger(self, I)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if TryStrToFloat(CurrentToken, X, ExprFormatSettings) then
|
if TryStrToFloat(CurrentToken, X, FFormatSettings) then
|
||||||
Result := TsConstExprNode.CreateFloat(X)
|
Result := TsConstExprNode.CreateFloat(self, X)
|
||||||
else
|
else
|
||||||
ParserError(Format(SErrInvalidFloat, [CurrentToken]));
|
ParserError(Format(SErrInvalidFloat, [CurrentToken]));
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if (TokenType = ttTrue) then
|
else if (TokenType = ttTrue) then
|
||||||
Result := TsConstExprNode.CreateBoolean(true)
|
Result := TsConstExprNode.CreateBoolean(self, true)
|
||||||
else if (TokenType = ttFalse) then
|
else if (TokenType = ttFalse) then
|
||||||
Result := TsConstExprNode.CreateBoolean(false)
|
Result := TsConstExprNode.CreateBoolean(self, false)
|
||||||
else if (TokenType = ttString) then
|
else if (TokenType = ttString) then
|
||||||
Result := TsConstExprNode.CreateString(CurrentToken)
|
Result := TsConstExprNode.CreateString(self, CurrentToken)
|
||||||
else if (TokenType = ttCell) then
|
else if (TokenType = ttCell) then
|
||||||
Result := TsCellExprNode.Create(FWorksheet, CurrentToken)
|
Result := TsCellExprNode.Create(self, FWorksheet, CurrentToken)
|
||||||
else if (TokenType = ttCellRange) then
|
else if (TokenType = ttCellRange) then
|
||||||
Result := TsCellRangeExprNode.Create(FWorksheet, CurrentToken)
|
Result := TsCellRangeExprNode.Create(self, FWorksheet, CurrentToken)
|
||||||
else if not (TokenType in [ttIdentifier{, ttIf}]) then
|
else if not (TokenType in [ttIdentifier]) then
|
||||||
ParserError(Format(SerrUnknownTokenAtPos, [Scanner.Pos, CurrentToken]))
|
ParserError(Format(SerrUnknownTokenAtPos, [Scanner.Pos, CurrentToken]))
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -1637,7 +1661,7 @@ begin
|
|||||||
optional := ID.IsOptionalArgument(AI+1);
|
optional := ID.IsOptionalArgument(AI+1);
|
||||||
if not optional then
|
if not optional then
|
||||||
begin
|
begin
|
||||||
if (TokenType <> ttComma) then
|
if (TokenType <> ttListSep) then
|
||||||
if (AI < abs(lCount)) then
|
if (AI < abs(lCount)) then
|
||||||
ParserError(Format(SErrCommaExpected, [Scanner.Pos, CurrentToken]))
|
ParserError(Format(SErrCommaExpected, [Scanner.Pos, CurrentToken]))
|
||||||
end;
|
end;
|
||||||
@ -1660,14 +1684,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
case ID.IdentifierType of
|
case ID.IdentifierType of
|
||||||
itVariable : Result := TsVariableExprNode.CreateIdentifier(ID);
|
itVariable:
|
||||||
itFunctionCallBack : Result := TsFunctionCallBackExprNode.CreateFunction(ID, Args);
|
Result := TsVariableExprNode.CreateIdentifier(self, ID);
|
||||||
itFunctionHandler : Result := TFPFunctionEventHandlerExprNode.CreateFunction(ID, Args);
|
itFunctionCallBack:
|
||||||
|
Result := TsFunctionCallBackExprNode.CreateFunction(self, ID, Args);
|
||||||
|
itFunctionHandler:
|
||||||
|
Result := TFPFunctionEventHandlerExprNode.CreateFunction(self, ID, Args);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
GetToken;
|
GetToken;
|
||||||
if TokenType = ttPercent then begin
|
if TokenType = ttPercent then begin
|
||||||
Result := TsPercentExprNode.Create(Result);
|
Result := TsPercentExprNode.Create(self, Result);
|
||||||
GetToken;
|
GetToken;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1687,10 +1714,37 @@ begin
|
|||||||
FDirty := true;
|
FDirty := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsExpressionParser.GetExpression: String;
|
||||||
|
var
|
||||||
|
fs: TFormatsettings;
|
||||||
|
begin
|
||||||
|
fs := DefaultFormatSettings;
|
||||||
|
fs.DecimalSeparator := '.';
|
||||||
|
fs.ListSeparator := ',';
|
||||||
|
Result := BuildStringFormula(fs);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsExpressionParser.GetLocalizedExpression(const AFormatSettings: TFormatSettings): String;
|
||||||
|
begin
|
||||||
|
Result := BuildStringFormula(AFormatSettings);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsExpressionParser.SetExpression(const AValue: String);
|
procedure TsExpressionParser.SetExpression(const AValue: String);
|
||||||
|
var
|
||||||
|
fs: TFormatSettings;
|
||||||
|
begin
|
||||||
|
fs := DefaultFormatSettings;
|
||||||
|
fs.DecimalSeparator := '.';
|
||||||
|
fs.ListSeparator := ',';
|
||||||
|
SetLocalizedExpression(fs, AValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsExpressionParser.SetLocalizedExpression(const AFormatSettings: TFormatSettings;
|
||||||
|
const AValue: String);
|
||||||
begin
|
begin
|
||||||
if FExpression = AValue then
|
if FExpression = AValue then
|
||||||
exit;
|
exit;
|
||||||
|
FFormatSettings := AFormatSettings;
|
||||||
FExpression := AValue;
|
FExpression := AValue;
|
||||||
if (AValue <> '') and (AValue[1] = '=') then
|
if (AValue <> '') and (AValue[1] = '=') then
|
||||||
FScanner.Source := Copy(AValue, 2, Length(AValue))
|
FScanner.Source := Copy(AValue, 2, Length(AValue))
|
||||||
@ -1738,7 +1792,7 @@ procedure TsExpressionParser.SetRPNFormula(const AFormula: TsRPNFormula);
|
|||||||
r := AFormula[AIndex].Row;
|
r := AFormula[AIndex].Row;
|
||||||
c := AFormula[AIndex].Col;
|
c := AFormula[AIndex].Col;
|
||||||
flags := AFormula[AIndex].RelFlags;
|
flags := AFormula[AIndex].RelFlags;
|
||||||
ANode := TsCellExprNode.Create(FWorksheet, r, c, flags);
|
ANode := TsCellExprNode.Create(self, FWorksheet, r, c, flags);
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
fekCellRange:
|
fekCellRange:
|
||||||
@ -1748,32 +1802,32 @@ procedure TsExpressionParser.SetRPNFormula(const AFormula: TsRPNFormula);
|
|||||||
r2 := AFormula[AIndex].Row2;
|
r2 := AFormula[AIndex].Row2;
|
||||||
c2 := AFormula[AIndex].Col2;
|
c2 := AFormula[AIndex].Col2;
|
||||||
flags := AFormula[AIndex].RelFlags;
|
flags := AFormula[AIndex].RelFlags;
|
||||||
ANode := TsCellRangeExprNode.Create(FWorksheet, r, c, r2, c2, flags);
|
ANode := TsCellRangeExprNode.Create(self, FWorksheet, r, c, r2, c2, flags);
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
fekNum:
|
fekNum:
|
||||||
begin
|
begin
|
||||||
ANode := TsConstExprNode.CreateFloat(AFormula[AIndex].DoubleValue);
|
ANode := TsConstExprNode.CreateFloat(self, AFormula[AIndex].DoubleValue);
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
fekInteger:
|
fekInteger:
|
||||||
begin
|
begin
|
||||||
ANode := TsConstExprNode.CreateInteger(AFormula[AIndex].IntValue);
|
ANode := TsConstExprNode.CreateInteger(self, AFormula[AIndex].IntValue);
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
fekString:
|
fekString:
|
||||||
begin
|
begin
|
||||||
ANode := TsConstExprNode.CreateString(AFormula[AIndex].StringValue);
|
ANode := TsConstExprNode.CreateString(self, AFormula[AIndex].StringValue);
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
fekBool:
|
fekBool:
|
||||||
begin
|
begin
|
||||||
ANode := TsConstExprNode.CreateBoolean(AFormula[AIndex].DoubleValue <> 0.0);
|
ANode := TsConstExprNode.CreateBoolean(self, AFormula[AIndex].DoubleValue <> 0.0);
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
fekErr:
|
fekErr:
|
||||||
begin
|
begin
|
||||||
ANode := TsConstExprNode.CreateError(TsErrorValue(AFormula[AIndex].IntValue));
|
ANode := TsConstExprNode.CreateError(self, TsErrorValue(AFormula[AIndex].IntValue));
|
||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1783,10 +1837,10 @@ procedure TsExpressionParser.SetRPNFormula(const AFormula: TsRPNFormula);
|
|||||||
dec(AIndex);
|
dec(AIndex);
|
||||||
CreateNodeFromRPN(operand, AIndex);
|
CreateNodeFromRPN(operand, AIndex);
|
||||||
case fek of
|
case fek of
|
||||||
fekPercent : ANode := TsPercentExprNode.Create(operand);
|
fekPercent : ANode := TsPercentExprNode.Create(self, operand);
|
||||||
fekUMinus : ANode := TsUMinusExprNode.Create(operand);
|
fekUMinus : ANode := TsUMinusExprNode.Create(self, operand);
|
||||||
fekUPlus : ANode := TsUPlusExprNode.Create(operand);
|
fekUPlus : ANode := TsUPlusExprNode.Create(self, operand);
|
||||||
fekParen : ANode := TsParenthesisExprNode.Create(operand);
|
fekParen : ANode := TsParenthesisExprNode.Create(self, operand);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1802,18 +1856,18 @@ procedure TsExpressionParser.SetRPNFormula(const AFormula: TsRPNFormula);
|
|||||||
CreateNodeFromRPN(left, AIndex);
|
CreateNodeFromRPN(left, AIndex);
|
||||||
CheckNodes(left, right);
|
CheckNodes(left, right);
|
||||||
case fek of
|
case fek of
|
||||||
fekAdd : ANode := TsAddExprNode.Create(left, right);
|
fekAdd : ANode := TsAddExprNode.Create(self, left, right);
|
||||||
fekSub : ANode := TsSubtractExprNode.Create(left, right);
|
fekSub : ANode := TsSubtractExprNode.Create(self, left, right);
|
||||||
fekMul : ANode := TsMultiplyExprNode.Create(left, right);
|
fekMul : ANode := TsMultiplyExprNode.Create(self, left, right);
|
||||||
fekDiv : ANode := TsDivideExprNode.Create(left, right);
|
fekDiv : ANode := TsDivideExprNode.Create(self, left, right);
|
||||||
fekPower : ANode := TsPowerExprNode.Create(left, right);
|
fekPower : ANode := TsPowerExprNode.Create(self, left, right);
|
||||||
fekConcat : ANode := tsConcatExprNode.Create(left, right);
|
fekConcat : ANode := tsConcatExprNode.Create(self, left, right);
|
||||||
fekEqual : ANode := TsEqualExprNode.Create(left, right);
|
fekEqual : ANode := TsEqualExprNode.Create(self, left, right);
|
||||||
fekNotEqual : ANode := TsNotEqualExprNode.Create(left, right);
|
fekNotEqual : ANode := TsNotEqualExprNode.Create(self, left, right);
|
||||||
fekGreater : ANode := TsGreaterExprNode.Create(left, right);
|
fekGreater : ANode := TsGreaterExprNode.Create(self, left, right);
|
||||||
fekGreaterEqual: ANode := TsGreaterEqualExprNode.Create(left, right);
|
fekGreaterEqual: ANode := TsGreaterEqualExprNode.Create(self, left, right);
|
||||||
fekLess : ANode := TsLessExprNode.Create(left, right);
|
fekLess : ANode := TsLessExprNode.Create(self, left, right);
|
||||||
fekLessEqual : ANode := tsLessEqualExprNode.Create(left, right);
|
fekLessEqual : ANode := tsLessEqualExprNode.Create(self, left, right);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1836,9 +1890,12 @@ procedure TsExpressionParser.SetRPNFormula(const AFormula: TsRPNFormula);
|
|||||||
for i:=n-1 downto 0 do
|
for i:=n-1 downto 0 do
|
||||||
CreateNodeFromRPN(args[i], AIndex);
|
CreateNodeFromRPN(args[i], AIndex);
|
||||||
case ID.IdentifierType of
|
case ID.IdentifierType of
|
||||||
itVariable : ANode := TsVariableExprNode.CreateIdentifier(ID);
|
itVariable:
|
||||||
itFunctionCallBack : ANode := TsFunctionCallBackExprNode.CreateFunction(ID, args);
|
ANode := TsVariableExprNode.CreateIdentifier(self, ID);
|
||||||
itFunctionHandler : ANode := TFPFunctionEventHandlerExprNode.CreateFunction(ID, args);
|
itFunctionCallBack:
|
||||||
|
ANode := TsFunctionCallBackExprNode.CreateFunction(self, ID, args);
|
||||||
|
itFunctionHandler:
|
||||||
|
ANode := TFPFunctionEventHandlerExprNode.CreateFunction(self, ID, args);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -2127,6 +2184,11 @@ begin
|
|||||||
Result := FValue.ResString;
|
Result := FValue.ResString;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsExprIdentifierDef.GetFormatSettings: TFormatSettings;
|
||||||
|
begin
|
||||||
|
Result := TsExprIdentifierDefs(Collection).Parser.FFormatSettings;
|
||||||
|
end;
|
||||||
|
|
||||||
function TsExprIdentifierDef.GetResultType: TsResultType;
|
function TsExprIdentifierDef.GetResultType: TsResultType;
|
||||||
begin
|
begin
|
||||||
Result := FValue.ResultType;
|
Result := FValue.ResultType;
|
||||||
@ -2136,12 +2198,12 @@ function TsExprIdentifierDef.GetValue: String;
|
|||||||
begin
|
begin
|
||||||
case FValue.ResultType of
|
case FValue.ResultType of
|
||||||
rtBoolean : if FValue.ResBoolean then
|
rtBoolean : if FValue.ResBoolean then
|
||||||
Result := 'True'
|
Result := 'TRUE'
|
||||||
else
|
else
|
||||||
Result := 'False';
|
Result := 'FALSE';
|
||||||
rtInteger : Result := IntToStr(FValue.ResInteger);
|
rtInteger : Result := IntToStr(FValue.ResInteger);
|
||||||
rtFloat : Result := FloatToStr(FValue.ResFloat, ExprFormatSettings);
|
rtFloat : Result := FloatToStr(FValue.ResFloat, GetFormatSettings);
|
||||||
rtDateTime : Result := FormatDateTime('cccc', FValue.ResDateTime);
|
rtDateTime : Result := FormatDateTime('cccc', FValue.ResDateTime, GetFormatSettings);
|
||||||
rtString : Result := FValue.ResString;
|
rtString : Result := FValue.ResString;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -2216,7 +2278,7 @@ procedure TsExprIdentifierDef.SetAsString(const AValue: String);
|
|||||||
begin
|
begin
|
||||||
CheckVariable;
|
CheckVariable;
|
||||||
CheckResultType(rtString);
|
CheckResultType(rtString);
|
||||||
FValue.resString := AValue;
|
FValue.ResString := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsExprIdentifierDef.SetName(const AValue: ShortString);
|
procedure TsExprIdentifierDef.SetName(const AValue: ShortString);
|
||||||
@ -2243,10 +2305,10 @@ begin
|
|||||||
FStringValue := AValue;
|
FStringValue := AValue;
|
||||||
if (AValue <> '') then
|
if (AValue <> '') then
|
||||||
case FValue.ResultType of
|
case FValue.ResultType of
|
||||||
rtBoolean : FValue.ResBoolean := FStringValue='True';
|
rtBoolean : FValue.ResBoolean := (FStringValue='True');
|
||||||
rtInteger : FValue.ResInteger := StrToInt(AValue);
|
rtInteger : FValue.ResInteger := StrToInt(AValue);
|
||||||
rtFloat : FValue.ResFloat := StrToFloat(AValue);
|
rtFloat : FValue.ResFloat := StrToFloat(AValue, GetFormatSettings);
|
||||||
rtDateTime : FValue.ResDateTime := StrToDateTime(AValue);
|
rtDateTime : FValue.ResDateTime := StrToDateTime(AValue, GetFormatSettings);
|
||||||
rtString : FValue.ResString := AValue;
|
rtString : FValue.ResString := AValue;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -2411,8 +2473,10 @@ end;
|
|||||||
|
|
||||||
{ TsUnaryOperationExprNode }
|
{ TsUnaryOperationExprNode }
|
||||||
|
|
||||||
constructor TsUnaryOperationExprNode.Create(AOperand: TsExprNode);
|
constructor TsUnaryOperationExprNode.Create(AParser: TsExpressionParser;
|
||||||
|
AOperand: TsExprNode);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FOperand := AOperand;
|
FOperand := AOperand;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2431,8 +2495,10 @@ end;
|
|||||||
|
|
||||||
{ TsBinaryOperationExprNode }
|
{ TsBinaryOperationExprNode }
|
||||||
|
|
||||||
constructor TsBinaryOperationExprNode.Create(ALeft, ARight: TsExprNode);
|
constructor TsBinaryOperationExprNode.Create(AParser: TsExpressionParser;
|
||||||
|
ALeft, ARight: TsExprNode);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FLeft := ALeft;
|
FLeft := ALeft;
|
||||||
FRight := ARight;
|
FRight := ARight;
|
||||||
end;
|
end;
|
||||||
@ -2481,39 +2547,50 @@ end;
|
|||||||
|
|
||||||
{ TsConstExprNode }
|
{ TsConstExprNode }
|
||||||
|
|
||||||
constructor TsConstExprNode.CreateString(AValue: String);
|
constructor TsConstExprNode.CreateString(AParser: TsExpressionParser;
|
||||||
|
AValue: String);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FValue.ResultType := rtString;
|
FValue.ResultType := rtString;
|
||||||
FValue.ResString := AValue;
|
FValue.ResString := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsConstExprNode.CreateInteger(AValue: Int64);
|
constructor TsConstExprNode.CreateInteger(AParser: TsExpressionParser;
|
||||||
|
AValue: Int64);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FValue.ResultType := rtInteger;
|
FValue.ResultType := rtInteger;
|
||||||
FValue.ResInteger := AValue;
|
FValue.ResInteger := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsConstExprNode.CreateDateTime(AValue: TDateTime);
|
constructor TsConstExprNode.CreateDateTime(AParser: TsExpressionParser;
|
||||||
|
AValue: TDateTime);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FValue.ResultType := rtDateTime;
|
FValue.ResultType := rtDateTime;
|
||||||
FValue.ResDateTime := AValue;
|
FValue.ResDateTime := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsConstExprNode.CreateFloat(AValue: TsExprFloat);
|
constructor TsConstExprNode.CreateFloat(AParser: TsExpressionParser;
|
||||||
|
AValue: TsExprFloat);
|
||||||
begin
|
begin
|
||||||
Inherited Create;
|
FParser := AParser;
|
||||||
FValue.ResultType := rtFloat;
|
FValue.ResultType := rtFloat;
|
||||||
FValue.ResFloat := AValue;
|
FValue.ResFloat := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsConstExprNode.CreateBoolean(AValue: Boolean);
|
constructor TsConstExprNode.CreateBoolean(AParser: TsExpressionParser;
|
||||||
|
AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FValue.ResultType := rtBoolean;
|
FValue.ResultType := rtBoolean;
|
||||||
FValue.ResBoolean := AValue;
|
FValue.ResBoolean := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsConstExprNode.CreateError(AValue: TsErrorValue);
|
constructor TsConstExprNode.CreateError(AParser: TsExpressionParser;
|
||||||
|
AValue: TsErrorValue);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FValue.ResultType := rtError;
|
FValue.ResultType := rtError;
|
||||||
FValue.ResError := AValue;
|
FValue.ResError := AValue;
|
||||||
end;
|
end;
|
||||||
@ -2538,9 +2615,9 @@ begin
|
|||||||
case NodeType of
|
case NodeType of
|
||||||
rtString : Result := cDoubleQuote + FValue.ResString + cDoubleQuote;
|
rtString : Result := cDoubleQuote + FValue.ResString + cDoubleQuote;
|
||||||
rtInteger : Result := IntToStr(FValue.ResInteger);
|
rtInteger : Result := IntToStr(FValue.ResInteger);
|
||||||
rtDateTime : Result := '''' + FormatDateTime('cccc', FValue.ResDateTime) + ''''; // Probably wrong !!!
|
rtDateTime : Result := '''' + FormatDateTime('cccc', FValue.ResDateTime, Parser.FFormatSettings) + ''''; // Probably wrong !!!
|
||||||
rtBoolean : if FValue.ResBoolean then Result := 'TRUE' else Result := 'FALSE';
|
rtBoolean : if FValue.ResBoolean then Result := 'TRUE' else Result := 'FALSE';
|
||||||
rtFloat : Result := FloatToStr(FValue.ResFloat, ExprFormatSettings);
|
rtFloat : Result := FloatToStr(FValue.ResFloat, Parser.FFormatSettings);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3419,9 +3496,10 @@ end;
|
|||||||
|
|
||||||
{ TsIdentifierExprNode }
|
{ TsIdentifierExprNode }
|
||||||
|
|
||||||
constructor TsIdentifierExprNode.CreateIdentifier(AID: TsExprIdentifierDef);
|
constructor TsIdentifierExprNode.CreateIdentifier(AParser: TsExpressionParser;
|
||||||
|
AID: TsExprIdentifierDef);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
FParser := AParser;
|
||||||
FID := AID;
|
FID := AID;
|
||||||
PResult := @FID.FValue;
|
PResult := @FID.FValue;
|
||||||
FResultType := FID.ResultType;
|
FResultType := FID.ResultType;
|
||||||
@ -3459,10 +3537,10 @@ end;
|
|||||||
|
|
||||||
{ TsFunctionExprNode }
|
{ TsFunctionExprNode }
|
||||||
|
|
||||||
constructor TsFunctionExprNode.CreateFunction(AID: TsExprIdentifierDef;
|
constructor TsFunctionExprNode.CreateFunction(AParser: TsExpressionParser;
|
||||||
const Args: TsExprArgumentArray);
|
AID: TsExprIdentifierDef; const Args: TsExprArgumentArray);
|
||||||
begin
|
begin
|
||||||
inherited CreateIdentifier(AID);
|
inherited CreateIdentifier(AParser, AID);
|
||||||
FArgumentNodes := Args;
|
FArgumentNodes := Args;
|
||||||
SetLength(FArgumentParams, Length(Args));
|
SetLength(FArgumentParams, Length(Args));
|
||||||
end;
|
end;
|
||||||
@ -3500,7 +3578,7 @@ begin
|
|||||||
for i := 0 to Length(FArgumentNodes)-1 do
|
for i := 0 to Length(FArgumentNodes)-1 do
|
||||||
begin
|
begin
|
||||||
if (S <> '') then
|
if (S <> '') then
|
||||||
S := S + ',';
|
S := S + Parser.FFormatSettings.ListSeparator;
|
||||||
S := S + FArgumentNodes[i].AsString;
|
S := S + FArgumentNodes[i].AsString;
|
||||||
end;
|
end;
|
||||||
S := '(' + S + ')';
|
S := '(' + S + ')';
|
||||||
@ -3544,18 +3622,20 @@ begin
|
|||||||
begin
|
begin
|
||||||
rta := FArgumentNodes[i].NodeType;
|
rta := FArgumentNodes[i].NodeType;
|
||||||
|
|
||||||
// A "cell" can return any type --> no type conversion required here.
|
|
||||||
if rta = rtCell then
|
|
||||||
Continue;
|
|
||||||
|
|
||||||
if i+1 <= Length(FID.ParameterTypes) then
|
if i+1 <= Length(FID.ParameterTypes) then
|
||||||
begin
|
begin
|
||||||
rtp := CharToResultType(FID.ParameterTypes[i+1]);
|
rtp := CharToResultType(FID.ParameterTypes[i+1]);
|
||||||
lastrtp := rtp;
|
lastrtp := rtp;
|
||||||
end else
|
end else
|
||||||
rtp := lastrtp;
|
rtp := lastrtp;
|
||||||
|
|
||||||
if rtp = rtAny then
|
if rtp = rtAny then
|
||||||
Continue;
|
Continue;
|
||||||
|
// A "cell" can return any type --> no type conversion required here.
|
||||||
|
|
||||||
|
if rta = rtCell then
|
||||||
|
Continue;
|
||||||
|
|
||||||
if (rtp <> rta) and not (rta in [rtCellRange, rtError, rtEmpty]) then
|
if (rtp <> rta) and not (rta in [rtCellRange, rtError, rtEmpty]) then
|
||||||
begin
|
begin
|
||||||
// Automatically convert integers to floats in functions that return a float
|
// Automatically convert integers to floats in functions that return a float
|
||||||
@ -3575,8 +3655,8 @@ end;
|
|||||||
|
|
||||||
{ TsFunctionCallBackExprNode }
|
{ TsFunctionCallBackExprNode }
|
||||||
|
|
||||||
constructor TsFunctionCallBackExprNode.CreateFunction(AID: TsExprIdentifierDef;
|
constructor TsFunctionCallBackExprNode.CreateFunction(AParser: TsExpressionParser;
|
||||||
const Args: TsExprArgumentArray);
|
AID: TsExprIdentifierDef; const Args: TsExprArgumentArray);
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
FCallBack := AID.OnGetFunctionValueCallBack;
|
FCallBack := AID.OnGetFunctionValueCallBack;
|
||||||
@ -3593,8 +3673,8 @@ end;
|
|||||||
|
|
||||||
{ TFPFunctionEventHandlerExprNode }
|
{ TFPFunctionEventHandlerExprNode }
|
||||||
|
|
||||||
constructor TFPFunctionEventHandlerExprNode.CreateFunction(AID: TsExprIdentifierDef;
|
constructor TFPFunctionEventHandlerExprNode.CreateFunction(AParser: TsExpressionParser;
|
||||||
const Args: TsExprArgumentArray);
|
AID: TsExprIdentifierDef; const Args: TsExprArgumentArray);
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
FCallBack := AID.OnGetFunctionValue;
|
FCallBack := AID.OnGetFunctionValue;
|
||||||
@ -3611,18 +3691,20 @@ end;
|
|||||||
|
|
||||||
{ TsCellExprNode }
|
{ TsCellExprNode }
|
||||||
|
|
||||||
constructor TsCellExprNode.Create(AWorksheet: TsWorksheet; ACellString: String);
|
constructor TsCellExprNode.Create(AParser: TsExpressionParser;
|
||||||
|
AWorksheet: TsWorksheet; ACellString: String);
|
||||||
var
|
var
|
||||||
r, c: Cardinal;
|
r, c: Cardinal;
|
||||||
flags: TsRelFlags;
|
flags: TsRelFlags;
|
||||||
begin
|
begin
|
||||||
ParseCellString(ACellString, r, c, flags);
|
ParseCellString(ACellString, r, c, flags);
|
||||||
Create(AWorksheet, r, c, flags);
|
Create(AParser, AWorksheet, r, c, flags);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsCellExprNode.Create(AWorksheet: TsWorksheet; ARow,ACol: Cardinal;
|
constructor TsCellExprNode.Create(AParser: TsExpressionParser;
|
||||||
AFlags: TsRelFlags);
|
AWorksheet: TsWorksheet; ARow,ACol: Cardinal; AFlags: TsRelFlags);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FWorksheet := AWorksheet;
|
FWorksheet := AWorksheet;
|
||||||
FRow := ARow;
|
FRow := ARow;
|
||||||
FCol := ACol;
|
FCol := ACol;
|
||||||
@ -3696,7 +3778,8 @@ end;
|
|||||||
|
|
||||||
{ TsCellRangeExprNode }
|
{ TsCellRangeExprNode }
|
||||||
|
|
||||||
constructor TsCellRangeExprNode.Create(AWorksheet: TsWorksheet; ACellRangeString: String);
|
constructor TsCellRangeExprNode.Create(AParser: TsExpressionParser;
|
||||||
|
AWorksheet: TsWorksheet; ACellRangeString: String);
|
||||||
var
|
var
|
||||||
r1, c1, r2, c2: Cardinal;
|
r1, c1, r2, c2: Cardinal;
|
||||||
flags: TsRelFlags;
|
flags: TsRelFlags;
|
||||||
@ -3706,17 +3789,18 @@ begin
|
|||||||
ParseCellString(ACellRangeString, r1, c1, flags);
|
ParseCellString(ACellRangeString, r1, c1, flags);
|
||||||
if rfRelRow in flags then Include(flags, rfRelRow2);
|
if rfRelRow in flags then Include(flags, rfRelRow2);
|
||||||
if rfRelCol in flags then Include(flags, rfRelCol2);
|
if rfRelCol in flags then Include(flags, rfRelCol2);
|
||||||
Create(AWorksheet, r1, c1, r1, c1, flags);
|
Create(AParser, AWorksheet, r1, c1, r1, c1, flags);
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
ParseCellRangeString(ACellRangeString, r1, c1, r2, c2, flags);
|
ParseCellRangeString(ACellRangeString, r1, c1, r2, c2, flags);
|
||||||
Create(AWorksheet, r1, c1, r2, c2, flags);
|
Create(AParser, AWorksheet, r1, c1, r2, c2, flags);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TsCellRangeExprNode.Create(AWorksheet: TsWorksheet;
|
constructor TsCellRangeExprNode.Create(AParser: TsExpressionParser;
|
||||||
ARow1,ACol1,ARow2,ACol2: Cardinal; AFlags: TsRelFlags);
|
AWorksheet: TsWorksheet; ARow1,ACol1,ARow2,ACol2: Cardinal; AFlags: TsRelFlags);
|
||||||
begin
|
begin
|
||||||
|
FParser := AParser;
|
||||||
FWorksheet := AWorksheet;
|
FWorksheet := AWorksheet;
|
||||||
FRow1 := ARow1;
|
FRow1 := ARow1;
|
||||||
FCol1 := ACol1;
|
FCol1 := ACol1;
|
||||||
|
@ -1463,20 +1463,20 @@ begin
|
|||||||
|
|
||||||
// Statistical
|
// Statistical
|
||||||
cat := bcStatistics;
|
cat := bcStatistics;
|
||||||
AddFunction(cat, 'AVEDEV', 'F', '?+', INT_EXCEL_SHEET_FUNC_AVEDEV, @fpsAVEDEV);
|
AddFunction(cat, 'AVEDEV', 'F', 'F+', INT_EXCEL_SHEET_FUNC_AVEDEV, @fpsAVEDEV);
|
||||||
AddFunction(cat, 'AVERAGE', 'F', '?+', INT_EXCEL_SHEET_FUNC_AVERAGE, @fpsAVERAGE);
|
AddFunction(cat, 'AVERAGE', 'F', 'F+', INT_EXCEL_SHEET_FUNC_AVERAGE, @fpsAVERAGE);
|
||||||
AddFunction(cat, 'COUNT', 'I', '?+', INT_EXCEL_SHEET_FUNC_COUNT, @fpsCOUNT);
|
AddFunction(cat, 'COUNT', 'I', '?+', INT_EXCEL_SHEET_FUNC_COUNT, @fpsCOUNT);
|
||||||
AddFunction(cat, 'COUNTA', 'I', '?+', INT_EXCEL_SHEET_FUNC_COUNTA, @fpsCOUNTA);
|
AddFunction(cat, 'COUNTA', 'I', '?+', INT_EXCEL_SHEET_FUNC_COUNTA, @fpsCOUNTA);
|
||||||
AddFunction(cat, 'COUNTBLANK','I', 'R', INT_EXCEL_SHEET_FUNC_COUNTBLANK, @fpsCOUNTBLANK);
|
AddFunction(cat, 'COUNTBLANK','I', 'R', INT_EXCEL_SHEET_FUNC_COUNTBLANK, @fpsCOUNTBLANK);
|
||||||
AddFunction(cat, 'MAX', 'F', '?+', INT_EXCEL_SHEET_FUNC_MAX, @fpsMAX);
|
AddFunction(cat, 'MAX', 'F', 'F+', INT_EXCEL_SHEET_FUNC_MAX, @fpsMAX);
|
||||||
AddFunction(cat, 'MIN', 'F', '?+', INT_EXCEL_SHEET_FUNC_MIN, @fpsMIN);
|
AddFunction(cat, 'MIN', 'F', 'F+', INT_EXCEL_SHEET_FUNC_MIN, @fpsMIN);
|
||||||
AddFunction(cat, 'PRODUCT', 'F', '?+', INT_EXCEL_SHEET_FUNC_PRODUCT, @fpsPRODUCT);
|
AddFunction(cat, 'PRODUCT', 'F', 'F+', INT_EXCEL_SHEET_FUNC_PRODUCT, @fpsPRODUCT);
|
||||||
AddFunction(cat, 'STDEV', 'F', '?+', INT_EXCEL_SHEET_FUNC_STDEV, @fpsSTDEV);
|
AddFunction(cat, 'STDEV', 'F', 'F+', INT_EXCEL_SHEET_FUNC_STDEV, @fpsSTDEV);
|
||||||
AddFunction(cat, 'STDEVP', 'F', '?+', INT_EXCEL_SHEET_FUNC_STDEVP, @fpsSTDEVP);
|
AddFunction(cat, 'STDEVP', 'F', 'F+', INT_EXCEL_SHEET_FUNC_STDEVP, @fpsSTDEVP);
|
||||||
AddFunction(cat, 'SUM', 'F', '?+', INT_EXCEL_SHEET_FUNC_SUM, @fpsSUM);
|
AddFunction(cat, 'SUM', 'F', 'F+', INT_EXCEL_SHEET_FUNC_SUM, @fpsSUM);
|
||||||
AddFunction(cat, 'SUMSQ', 'F', '?+', INT_EXCEL_SHEET_FUNC_SUMSQ, @fpsSUMSQ);
|
AddFunction(cat, 'SUMSQ', 'F', 'F+', INT_EXCEL_SHEET_FUNC_SUMSQ, @fpsSUMSQ);
|
||||||
AddFunction(cat, 'VAR', 'F', '?+', INT_EXCEL_SHEET_FUNC_VAR, @fpsVAR);
|
AddFunction(cat, 'VAR', 'F', 'F+', INT_EXCEL_SHEET_FUNC_VAR, @fpsVAR);
|
||||||
AddFunction(cat, 'VARP', 'F', '?+', INT_EXCEL_SHEET_FUNC_VARP, @fpsVARP);
|
AddFunction(cat, 'VARP', 'F', 'F+', INT_EXCEL_SHEET_FUNC_VARP, @fpsVARP);
|
||||||
// to do: CountIF, SUMIF
|
// to do: CountIF, SUMIF
|
||||||
|
|
||||||
// Info functions
|
// Info functions
|
||||||
|
@ -2668,7 +2668,6 @@ begin
|
|||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Converts an RPN formula (as read from an xls biff file, for example) to a
|
Converts an RPN formula (as read from an xls biff file, for example) to a
|
||||||
string formula.
|
string formula.
|
||||||
@ -2685,7 +2684,7 @@ begin
|
|||||||
parser := TsSpreadsheetParser.Create(self);
|
parser := TsSpreadsheetParser.Create(self);
|
||||||
try
|
try
|
||||||
parser.RPNFormula := AFormula;
|
parser.RPNFormula := AFormula;
|
||||||
Result := parser.BuildStringFormula;
|
Result := parser.Expression;
|
||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
|
Reference in New Issue
Block a user