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"/>
</Item1>
</RequiredPackages>
<Units Count="1">
<Units Count="2">
<Unit0>
<Filename Value="demo_expression_parser.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="demo_expression_parser"/>
</Unit0>
<Unit1>
<Filename Value="..\..\fpsexprparser.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="fpsExprParser"/>
</Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

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

View File

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