Skip to content

Commit c0d18df

Browse files
committed
Merge branch 'dev'
2 parents 8fa2608 + acc3518 commit c0d18df

18 files changed

+508
-280
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ lib
1212
iOSDevice32
1313
*.tvsconfig
1414
*.mes
15+
*.stat
16+
*.dcu

boss.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Sempare Template Engine",
33
"description": "Sempare Template Engine for Delphi allows for flexible text manipulation. It can be used for generating email, html, source code, xml, configuration, etc.",
4-
"version": "1.7.2",
4+
"version": "1.7.3",
55
"homepage": "https://github.com/sempare/sempare-delphi-template-engine",
66
"mainsrc": "./src/",
77
"projects": [],

src/Sempare.Template.AST.pas

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,42 @@ ETemplate = class(Exception);
594594
procedure VisitStmt(const AStmt: IStmt);
595595
end;
596596

597+
TAbstractBase = class abstract(TInterfacedObject, IPositional, ITemplateVisitorHost)
598+
private
599+
FPosition: IPosition;
600+
function GetPosition: IPosition;
601+
function GetFilename: string;
602+
procedure SetFilename(const AFilename: string);
603+
function GetLine: integer;
604+
procedure SetLine(const Aline: integer);
605+
function GetPos: integer;
606+
procedure SetPos(const Apos: integer);
607+
public
608+
constructor Create(const APosition: IPosition);
609+
destructor Destroy; override;
610+
procedure Accept(const AVisitor: ITemplateVisitor); virtual; abstract;
611+
end;
612+
613+
TAbstractStmt = class abstract(TAbstractBase, IStmt)
614+
protected
615+
function Flatten: TArray<IStmt>; virtual;
616+
function GetHasEnd: boolean; virtual;
617+
public
618+
constructor Create(const APosition: IPosition);
619+
end;
620+
621+
TAbstractExpr = class abstract(TAbstractBase, IExpr)
622+
end;
623+
624+
TMapExpr = class(TAbstractExpr, IMapExpr)
625+
private
626+
FValue: TMap;
627+
function GetMap: TMap;
628+
public
629+
constructor Create(const APosition: IPosition; const AValue: TMap);
630+
procedure Accept(const AVisitor: ITemplateVisitor); override;
631+
end;
632+
597633
const
598634
StripDirectionStr: array [TStripDirection] of string = ( //
599635
'sdEnd', 'sdLeft', 'sdRight', 'sdBeforeNewLine', 'sdAfterNewLine');
@@ -624,4 +660,88 @@ function TStringActionsHelper.ToString: string;
624660
end;
625661
end;
626662

663+
{ TMapExpr }
664+
665+
procedure TMapExpr.Accept(const AVisitor: ITemplateVisitor);
666+
begin
667+
AVisitor.Visit(self);
668+
end;
669+
670+
constructor TMapExpr.Create(const APosition: IPosition; const AValue: TMap);
671+
begin
672+
inherited Create(APosition);
673+
FValue := AValue;
674+
end;
675+
676+
function TMapExpr.GetMap: TMap;
677+
begin
678+
exit(FValue);
679+
end;
680+
681+
{ TAbstractBase }
682+
683+
constructor TAbstractBase.Create(const APosition: IPosition);
684+
begin
685+
FPosition := APosition;
686+
end;
687+
688+
destructor TAbstractBase.Destroy;
689+
begin
690+
FPosition := nil;
691+
inherited;
692+
end;
693+
694+
function TAbstractBase.GetFilename: string;
695+
begin
696+
exit(FPosition.FileName);
697+
end;
698+
699+
function TAbstractBase.GetLine: integer;
700+
begin
701+
exit(FPosition.Line);
702+
end;
703+
704+
function TAbstractBase.GetPos: integer;
705+
begin
706+
exit(FPosition.Pos);
707+
end;
708+
709+
function TAbstractBase.GetPosition: IPosition;
710+
begin
711+
exit(FPosition);
712+
end;
713+
714+
procedure TAbstractBase.SetFilename(const AFilename: string);
715+
begin
716+
FPosition.FileName := AFilename;
717+
end;
718+
719+
procedure TAbstractBase.SetLine(const Aline: integer);
720+
begin
721+
FPosition.Line := Aline;
722+
end;
723+
724+
procedure TAbstractBase.SetPos(const Apos: integer);
725+
begin
726+
FPosition.Pos := Apos;
727+
end;
728+
729+
{ TAbstractStmt }
730+
731+
constructor TAbstractStmt.Create(const APosition: IPosition);
732+
begin
733+
inherited Create(APosition);
734+
end;
735+
736+
function TAbstractStmt.Flatten: TArray<IStmt>;
737+
begin
738+
SetLength(result, 1);
739+
result[0] := self;
740+
end;
741+
742+
function TAbstractStmt.GetHasEnd: boolean;
743+
begin
744+
exit(false);
745+
end;
746+
627747
end.

src/Sempare.Template.Common.pas

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ ETemplateEvaluationError = class(ETemplate, IPosition)
6666
property Position: IPosition read FPosition write FPosition implements IPosition;
6767
end;
6868

69+
ETemplateVariableNotResolved = class(ETemplate);
70+
6971
ITemplateVariables = interface
7072
['{8C2D166D-2AC1-47AB-985E-2CFD5D44271D}']
7173
function GetItem(const AKey: string): TTemplateValue;
@@ -108,11 +110,20 @@ procedure RaiseError(const APositional: IPosition; const AFormat: string); overl
108110
procedure RaiseErrorRes(const APositional: IPosition; const ResStringRec: PResStringRec; const AArgs: array of const); overload;
109111
procedure RaiseErrorRes(const APositional: IPosition; const ResStringRec: PResStringRec); overload;
110112

113+
function GetSempareVersion(): string;
114+
111115
implementation
112116

113117
uses
114118
Sempare.Template;
115119

120+
{$INCLUDE 'Sempare.Template.Version.inc'}
121+
122+
function GetSempareVersion(): string;
123+
begin
124+
exit(format('%d.%d.%d', [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION]));
125+
end;
126+
116127
procedure AcceptVisitor(const ATemplate: ITemplate; const AVisitor: ITemplateVisitor); overload;
117128
begin
118129
if not assigned(ATemplate) then

src/Sempare.Template.Context.pas

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ interface
8383
TPrettyPrintOutput = reference to procedure(const APrettyPrint: string);
8484
TTemplateResolver = reference to function(const AContext: ITemplateContext; const AName: string): ITemplate;
8585
TTemplateResolverWithContext = reference to function(const AContext: ITemplateContext; const AName: string; const AResolveContext: TTemplateValue; out ACacheInContext: boolean): ITemplate;
86+
TTemplateVariableResolver = reference to function(const AContext: ITemplateContext; const AName: string; out AResult: TValue): boolean;
8687

8788
ITemplateEvaluationContext = interface
8889
['{FCE6891F-3D39-4CC4-8ADB-024D843C7770}']
@@ -168,6 +169,9 @@ interface
168169
function GetWhitespace: char;
169170
procedure SetWhiteSpace(const AWS: char);
170171

172+
function GetVariableResolver: TTemplateVariableResolver;
173+
procedure SetVariableResolver(const AResolver: TTemplateVariableResolver);
174+
171175
property Functions: ITemplateFunctions read GetFunctions write SetFunctions;
172176
property NewLine: string read GetNewLine write SetNewLine;
173177
property WhitespaceChar: char read GetWhitespace write SetWhiteSpace;
@@ -186,6 +190,7 @@ interface
186190
property StartStripToken: string read GetScriptStartStripToken write SetScriptStartStripToken;
187191
property EndStripToken: string read GetScriptEndStripToken write SetScriptEndStripToken;
188192

193+
property VariableResolver: TTemplateVariableResolver read GetVariableResolver write SetVariableResolver;
189194
property ValueSeparator: char read GetValueSeparator write SetValueSeparator;
190195
property DecimalSeparator: char read GetDecimalSeparator write SetDecimalSeparator;
191196
property FormatSettings: TFormatSettings read GetFormatSettings;
@@ -274,6 +279,7 @@ TTemplateContext = class(TInterfacedObject, ITemplateContext, ITemplateContext
274279
FDebugFormat: string;
275280
FPrettyPrintOutput: TPrettyPrintOutput;
276281
FWhiteSpace: char;
282+
FVariableResolver: TTemplateVariableResolver;
277283
public
278284
constructor Create(const AOptions: TTemplateEvaluationOptions);
279285
destructor Destroy; override;
@@ -361,6 +367,9 @@ TTemplateContext = class(TInterfacedObject, ITemplateContext, ITemplateContext
361367
function GetWhitespace: char;
362368
procedure SetWhiteSpace(const AWS: char);
363369

370+
function GetVariableResolver: TTemplateVariableResolver;
371+
procedure SetVariableResolver(const AResolver: TTemplateVariableResolver);
372+
364373
end;
365374

366375
function CreateTemplateContext(const AOptions: TTemplateEvaluationOptions): ITemplateContext;
@@ -526,7 +535,9 @@ function TTemplateContext.GetVariable(const AName: string): TValue;
526535
begin
527536
FLock.Acquire;
528537
try
529-
exit(FVariables[AName]);
538+
if TryGetVariable(AName, result) then
539+
exit;
540+
raise ETemplateVariableNotResolved.CreateResFmt(@SVariableNotResolved, [AName]);
530541
finally
531542
FLock.Release;
532543
end;
@@ -537,6 +548,11 @@ function TTemplateContext.GetVariableEncoder: TTemplateEncodeFunction;
537548
result := FVariableEncoder;
538549
end;
539550

551+
function TTemplateContext.GetVariableResolver: TTemplateVariableResolver;
552+
begin
553+
result := FVariableResolver;
554+
end;
555+
540556
function TTemplateContext.GetVariables: ITemplateVariables;
541557
begin
542558
exit(FVariables);
@@ -691,6 +707,11 @@ procedure TTemplateContext.SetVariableEncoder(const AEncoder: TTemplateEncodeFun
691707
FVariableEncoder := AEncoder;
692708
end;
693709

710+
procedure TTemplateContext.SetVariableResolver(const AResolver: TTemplateVariableResolver);
711+
begin
712+
FVariableResolver := AResolver;
713+
end;
714+
694715
procedure TTemplateContext.SetWhiteSpace(const AWS: char);
695716
begin
696717
FWhiteSpace := AWS;
@@ -766,10 +787,14 @@ function TTemplateContext.TryGetVariable(const AName: string; out AValue: TValue
766787
begin
767788
FLock.Enter;
768789
try
769-
exit(FVariables.TryGetItem(AName, AValue));
790+
if FVariables.TryGetItem(AName, AValue) then
791+
exit(true);
792+
if assigned(FVariableResolver) then
793+
exit(FVariableResolver(self, AName, AValue));
770794
finally
771795
FLock.Leave;
772796
end;
797+
exit(false);
773798
end;
774799

775800
procedure TTemplateContext.Unmanage(const AObject: TObject);

0 commit comments

Comments
 (0)