fpspreadsheet: Add string concatenation operation & to expression parser; remove string concatenation by means of "+"

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3501 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-08-22 10:54:55 +00:00
parent e122d42652
commit 5257052685
3 changed files with 70 additions and 17 deletions

View File

@ -36,12 +36,17 @@
<PackageName Value="LazUtils"/> <PackageName Value="LazUtils"/>
</Item1> </Item1>
</RequiredPackages> </RequiredPackages>
<Units Count="1"> <Units Count="2">
<Unit0> <Unit0>
<Filename Value="demo_expression_parser.pas"/> <Filename Value="demo_expression_parser.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="demo_expression_parser"/> <UnitName Value="demo_expression_parser"/>
</Unit0> </Unit0>
<Unit1>
<Filename Value="..\..\fpsexprparser.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="fpsExprParser"/>
</Unit1>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -31,14 +31,15 @@ begin
workbook := TsWorkbook.Create; workbook := TsWorkbook.Create;
try try
worksheet := workbook.AddWorksheet('Test'); worksheet := workbook.AddWorksheet('Test');
{
worksheet.WriteNumber(0, 0, 2); // A1 worksheet.WriteNumber(0, 0, 2); // A1
worksheet.WriteNumber(0, 1, 2.5); // B1 worksheet.WriteNumber(0, 1, 2.5); // B1
{ }
worksheet.WriteUTF8Text(0, 0, 'Hallo'); // A1 worksheet.WriteUTF8Text(0, 0, 'Hallo'); // A1
worksheet.WriteUTF8Text(0, 1, 'Welt'); // B1 worksheet.WriteUTF8Text(0, 1, 'World'); // B1
}
cell := worksheet.WriteFormula(1, 0, '=(A1+2)*3'); // A2 //cell := worksheet.WriteFormula(1, 0, '=(A1+2)*3'); // A2
cell := worksheet.WriteFormula(1, 0, 'A1&" "&B1');
WriteLn('A1 = ', worksheet.ReadAsUTF8Text(0, 0)); WriteLn('A1 = ', worksheet.ReadAsUTF8Text(0, 0));
WriteLn('B1 = ', worksheet.ReadAsUTF8Text(0, 1)); WriteLn('B1 = ', worksheet.ReadAsUTF8Text(0, 1));

View File

@ -15,7 +15,8 @@
Modified for integration into fpspreadsheet by Werner Pamler: Modified for integration into fpspreadsheet by Werner Pamler:
- Original file name: fpexprpars.pp - Original file name: fpexprpars.pp
- Rename identifiers to avoid naming conflicts with the original - Rename identifiers to avoid naming conflicts with the original
- TsExpressionParser and TsBuiltinExpressionManager are not components any more - TsExpressionParser and TsBuiltinExpressionManager are not components
any more
- TsExpressionParser is created with the worksheet as a parameter. - TsExpressionParser is created with the worksheet as a parameter.
- add new TExprNode classes: - add new TExprNode classes:
- TsCellExprNode for references to cells - TsCellExprNode for references to cells
@ -26,7 +27,7 @@
- remove and modifiy built-in function such that the parser is compatible - remove and modifiy built-in function such that the parser is compatible
with Excel syntax (and OpenOffice - which is the same). with Excel syntax (and OpenOffice - which is the same).
**********************************************************************} ******************************************************************************}
{$mode objfpc} {$mode objfpc}
{$h+} {$h+}
unit fpsExprParser; unit fpsExprParser;
@ -49,7 +50,7 @@ type
fekParen, fekParen,
*) *)
TTokenType = ( TTokenType = (
ttPlus, ttMinus, ttMul, ttDiv, 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,
ttNumber, ttString, ttIdentifier, ttCell, ttCellRange, ttNumber, ttString, ttIdentifier, ttCell, ttCellRange,
ttComma, ttAnd, ttOr, ttXor, ttTrue, ttFalse, ttNot, ttIf, ttComma, ttAnd, ttOr, ttXor, ttTrue, ttFalse, ttNot, ttIf,
@ -272,6 +273,17 @@ type
property Condition: TsExprNode read FCondition; property Condition: TsExprNode read FCondition;
end; end;
{ TsConcatExprNode }
TsConcatExprNode = class(TsBinaryOperationExprNode)
protected
procedure Check; override;
procedure GetNodeValue(var Result: TsExpressionResult); override;
function NodeType: TsResultType; override;
public
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
function AsString: string ; override;
end;
{ TsMathOperationExprNode } { TsMathOperationExprNode }
TsMathOperationExprNode = class(TsBinaryOperationExprNode) TsMathOperationExprNode = class(TsBinaryOperationExprNode)
protected protected
@ -914,7 +926,7 @@ begin
'/' : Result := ttDiv; '/' : Result := ttDiv;
'^' : Result := ttPower; '^' : Result := ttPower;
'%' : Result := ttPercent; '%' : Result := ttPercent;
'&' : Result := ttPlus; '&' : Result := ttConcat;
'<' : Result := ttLessThan; '<' : Result := ttLessThan;
'>' : Result := ttLargerThan; '>' : Result := ttLargerThan;
'=' : Result := ttEqual; '=' : Result := ttEqual;
@ -1356,7 +1368,7 @@ begin
{$ifdef debugexpr} Writeln('Level 3 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr} {$ifdef debugexpr} Writeln('Level 3 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
Result := Level4; Result := Level4;
try try
while TokenType in [ttPlus, ttMinus] do begin while TokenType in [ttPlus, ttMinus, ttConcat] do begin
tt := TokenType; tt := TokenType;
GetToken; GetToken;
CheckEOF; CheckEOF;
@ -1365,6 +1377,7 @@ begin
case tt of case tt of
ttPlus : Result := TsAddExprNode.Create(Result, right); ttPlus : Result := TsAddExprNode.Create(Result, right);
ttMinus : Result := TsSubtractExprNode.Create(Result, right); ttMinus : Result := TsSubtractExprNode.Create(Result, right);
ttConcat: Result := TsConcatExprNode.Create(Result, right);
end; end;
end; end;
except except
@ -1483,10 +1496,6 @@ begin
// Determine number of arguments // Determine number of arguments
if isIF then if isIF then
ACount := 3 ACount := 3
{
else if isCASE then
ACount := -4
}
else if (ID.IdentifierType in [itFunctionCallBack, itFunctionHandler]) then else if (ID.IdentifierType in [itFunctionCallBack, itFunctionHandler]) then
ACount := ID.ArgumentCount ACount := ID.ArgumentCount
else else
@ -2662,11 +2671,49 @@ begin
end; end;
{ TsConcatExprNode }
procedure TsConcatExprNode.Check;
begin
inherited Check;
CheckNodeType(Left, [rtString]);
CheckNodeType(Right, [rtString]);
end;
procedure TsConcatExprNode.GetNodeValue(var Result: TsExpressionResult);
var
RRes : TsExpressionResult;
begin
Left.GetNodeValue(Result);
Right.GetNodeValue(RRes);
Result.ResString := Result.ResString + RRes.ResString;
Result.ResultType := rtString;
end;
function TsConcatExprNode.NodeType: TsResultType;
begin
Result := rtString;
end;
function TsConcatExprNode.AsRPNItem(ANext: PRPNItem): PRPNItem;
begin
Result := RPNFunc(fekConcat,
Right.AsRPNItem(
Left.AsRPNItem(
nil)));
end;
function TsConcatExprNode.AsString: string;
begin
Result := Left.AsString + '&' + Right.AsString;
end;
{ TsMathOperationExprNode } { TsMathOperationExprNode }
procedure TsMathOperationExprNode.Check; procedure TsMathOperationExprNode.Check;
const const
AllowedTypes = [rtInteger, rtfloat, rtDateTime, rtString]; AllowedTypes = [rtInteger, rtfloat, rtDateTime];
begin begin
inherited Check; inherited Check;
CheckNodeType(Left, AllowedTypes); CheckNodeType(Left, AllowedTypes);
@ -2704,7 +2751,7 @@ begin
Right.GetNodeValue(RRes); Right.GetNodeValue(RRes);
case Result.ResultType of case Result.ResultType of
rtInteger : Result.ResInteger := Result.ResInteger + RRes.ResInteger; rtInteger : Result.ResInteger := Result.ResInteger + RRes.ResInteger;
rtString : Result.ResString := Result.ResString + RRes.ResString; // rtString : Result.ResString := Result.ResString + RRes.ResString;
rtDateTime : Result.ResDateTime := Result.ResDateTime + RRes.ResDateTime; rtDateTime : Result.ResDateTime := Result.ResDateTime + RRes.ResDateTime;
rtFloat : Result.ResFloat := Result.ResFloat + RRes.ResFloat; rtFloat : Result.ResFloat := Result.ResFloat + RRes.ResFloat;
end; end;