Parcourir la source

* reimplemented experssion parser

master
Bergmann89 il y a 11 ans
Parent
révision
756fd412a4
18 fichiers modifiés avec 668 ajouts et 478 suppressions
  1. +5
    -8
      uengShaderCodeGenerator.pas
  2. +41
    -32
      uengShaderFile.pas
  3. +350
    -270
      uengShaderFileExpression.pas
  4. +46
    -1
      uengShaderFileTypes.pas
  5. +159
    -105
      uengShaderPart.pas
  6. +1
    -1
      uengShaderPartCall.pas
  7. +32
    -0
      uengShaderPartClass.pas
  8. +4
    -4
      uengShaderPartCntr.pas
  9. +1
    -1
      uengShaderPartComment.pas
  10. +1
    -1
      uengShaderPartEcho.pas
  11. +20
    -18
      uengShaderPartIf.pas
  12. +1
    -1
      uengShaderPartInclude.pas
  13. +1
    -21
      uengShaderPartKeyValuePair.pas
  14. +1
    -1
      uengShaderPartMessage.pas
  15. +1
    -1
      uengShaderPartMeta.pas
  16. +1
    -1
      uengShaderPartParameter.pas
  17. +0
    -9
      uengShaderPartProc.pas
  18. +3
    -3
      uengShaderPartText.pas

+ 5
- 8
uengShaderCodeGenerator.pas Voir le fichier

@@ -12,16 +12,13 @@ uses
type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderCodeGenerator = class(TengShaderPartScope)
{ Code Loading & Storage }
{ General }
private
fProperties: TengShaderPartPropertyMap;

protected
fInherited: TengShaderPartList;
procedure UpdateInherited; virtual;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ General }
procedure UpdateCache; override;
public
constructor Create(const aParent: TengShaderPart); override;
destructor Destroy; override;
@@ -34,13 +31,13 @@ implementation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.UpdateInherited;
begin
// TODO
// DUMMY
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
procedure TengShaderCodeGenerator.UpdateCache;
begin
result := inherited ParseIntern(aArgs, aParams);
inherited UpdateCache;
UpdateInherited;
end;



+ 41
- 32
uengShaderFile.pas Voir le fichier

@@ -32,13 +32,16 @@ type
function GetGenerator(const aName: String): TengShaderCodeGenerator;
function GetGeneratorCount: Integer;
function GetGeneratorNames(const aIndex: Integer): String;
procedure UpdateClasses;
protected
function GetFilename: String; override;
function GetFileReader: IengShaderFileReader; override;
function GetFileWriter: IengShaderFileWriter; override;

{ General }
private
procedure UpdateClasses;
protected
procedure UpdateCache; override;
public
property Generator [const aName: String]: TengShaderCodeGenerator read GetGenerator;
property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames;
@@ -82,30 +85,6 @@ begin
else result := fClasses.Keys[aIndex-1];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.UpdateClasses;
var
l: TengShaderPart.TSearchResults;
p: TengShaderPart;
new, old: TengShaderPartClass;

begin
l := TengShaderPart.TSearchResults.Create;
try
fClasses.Clear;
FindAll([sfSearchChildren], [TengShaderPartClass], l);
for p in l do begin
new := (p as TengShaderPartClass);
old := fClasses[new.Name];
if Assigned(old) then
raise EengDuplicateIdentifier.Create(new.Name, new, old, self);
fClasses.Add(new.Name, new);
end;
finally
FreeAndNil(l);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderFile.GetFilename: String;
begin
@@ -128,6 +107,36 @@ begin
result := Parent.FileWriter;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.UpdateClasses;
var
sr: TengShaderPart.TSearchResults;
p: TengShaderPart;
new, old: TengShaderPartClass;
begin
sr := TengShaderPart.TSearchResults.Create([TengShaderPartClass]);
try
fClasses.Clear;
Find([sfSearchChildren], sr);
for p in sr do begin
new := (p as TengShaderPartClass);
old := fClasses[new.Name];
if Assigned(old) then
raise EengDuplicateIdentifier.Create(new.Name, new, old, self);
fClasses.Add(new.Name, new);
end;
finally
FreeAndNil(sr);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.UpdateCache;
begin
inherited UpdateCache;
UpdateClasses;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader);
var
@@ -153,7 +162,7 @@ begin
if (token <> '') then with args do
raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename, self);
if (Root = self) then
UpdateClasses;
UpdateCache;
finally
FreeAndNil(args);
end;
@@ -165,7 +174,7 @@ end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter);
var
l: TengShaderPart.TSearchResults;
sr: TengShaderPart.TSearchResults;
i: Integer;
sl: TStringList;
ms: TMemoryStream;
@@ -176,19 +185,19 @@ begin
if not Assigned(fFileWriter) then
fFileWriter := TengShaderFileWriter.Create;

l := TengShaderPart.TSearchResults.Create;
sr := TengShaderPart.TSearchResults.Create([TengShaderPartInclude]);
sl := TStringList.Create;
ms := TMemoryStream.Create;
try
FindAll([sfSearchChildren, sfCurrentFileOnly], [TengShaderPartInclude], l);
for i := 0 to l.Count-1 do
(l[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter);
Find([sfSearchChildren, sfChildrenFileOnly], sr);
for i := 0 to sr.Count-1 do
(sr[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter);
sl.Text := Text;
sl.SaveToStream(ms);
ms.Position := 0;
fFileWriter.SaveStream(aFilename, ms);
finally
FreeAndNil(l);
FreeAndNil(sr);
FreeAndNil(sl);
FreeAndNil(ms);
fFileWriter := nil;


+ 350
- 270
uengShaderFileExpression.pas Voir le fichier

@@ -7,25 +7,14 @@ interface

uses
Classes, SysUtils, variants,
uengShaderFileParser;
uengShaderPart, uengShaderFileParser;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengExpressionItem = class(TObject)
private
fOwner: TObject;
fLine: Integer;
fCol: Integer;
fFilename: String;
TengExpressionItem = class(TengShaderPart)
public
property Owner: TObject read fOwner;
property Line: Integer read fLine;
property Col: Integer read fCol;
property Filename: String read fFilename;

function GetText: String; virtual;
function GetValue: Variant; virtual;
constructor Create(const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aLine, aCol: Integer);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -33,9 +22,12 @@ type
private
fValue: Variant;
public
property Value: Variant read fValue;

function GetText: String; override;
function GetValue: Variant; override;
constructor Create(const aValue: Variant; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);

constructor Create(const aValue: Variant; const aLine, aCol: Integer);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -43,9 +35,12 @@ type
private
fName: String;
public
property Name: String read fName;

function GetText: String; override;
function GetValue: Variant; override;
constructor Create(const aName: String; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);

constructor Create(const aName: String; const aLine, aCol: Integer);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -53,13 +48,25 @@ type
private
fChild: TengExpressionItem;
public
property Child: TengExpressionItem read fChild write fChild;
property Child: TengExpressionItem read fChild;

function GetText: String; override;
function GetValue: Variant; override;
constructor Create(const aChild: TengExpressionItem; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);

constructor Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengExpressionOperation = class(TengExpressionItem)
protected
function GetWeight: Integer; virtual;
public
property Weight: Integer read GetWeight;
function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; virtual;
function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; virtual;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengExpressionUnaryOperator = (
opBinaryNot,
@@ -67,18 +74,22 @@ type
opDefined,
opSet
);
TengExpressionUnaryOperation = class(TengExpressionItem)
TengExpressionUnaryOperation = class(TengExpressionOperation)
private
fChild: TengExpressionItem;
fUnaryOp: TengExpressionUnaryOperator;
protected
function GetWeight: Integer; override;
public
property Child: TengExpressionItem read fChild write fChild;
property Child: TengExpressionItem read fChild;
property UnaryOp: TengExpressionUnaryOperator read fUnaryOp;

function GetText: String; override;
function GetValue: Variant; override;
function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;

constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
destructor Destroy; override;
end;

@@ -89,11 +100,13 @@ type
opLogicalOr, opLogicalAnd, opLogicalXor, // logical
opEquals, opLesser, opGreater, opLEquals, opGEquals, opUnequals // comparison
);
TengExpressionBinaryOperation = class(TengExpressionItem)
TengExpressionBinaryOperation = class(TengExpressionOperation)
private
fFirst: TengExpressionItem;
fSecond: TengExpressionItem;
fBinaryOp: TengExpressionBinaryOperator;
protected
function GetWeight: Integer; override;
public
property First: TengExpressionItem read fFirst write fFirst;
property Second: TengExpressionItem read fSecond write fSecond;
@@ -101,12 +114,14 @@ type

function GetText: String; override;
function GetValue: Variant; override;
function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;

constructor Create(const aOperator: TengExpressionBinaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aOperator: TengExpressionBinaryOperator; const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
destructor Destroy; override;
end;

function ParseExpression(const aOwner: TObject; const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;

implementation

@@ -126,7 +141,6 @@ const
TOKEN_OP_DEFINED, //opDefined
TOKEN_OP_SET //opSet
);

EXPRESSION_BINARY_OPERATIONS: array[TengExpressionBinaryOperator] of String = (
TOKEN_OP_BINARY_OR, //opBinaryOr
TOKEN_OP_BINARY_AND, //opBinaryAnd
@@ -146,17 +160,39 @@ const
TOKEN_OP_GREATER, //opGreater
TOKEN_OP_LEQUALS, //opLEquals
TOKEN_OP_GEQUALS, //opGEquals
TOKEN_OP_UNEQUALS //opUnequals,
TOKEN_OP_UNEQUALS //opUnequals
);

UNARY_OPERATION_WEIGHTS: array[TengExpressionUnaryOperator] of Integer = (
00, //opBinaryNot
00, //opLogicalNot
00, //opDefined
00 //opSet
);
BINARY_OPERATION_WEIGHTS: array[TengExpressionBinaryOperator] of Integer = (
01, //opBinaryOr
02, //opBinaryAnd
03, //opBinaryXor

04, //opMultiply
05, //opDivide
06, //opAdd
07, //opSubtract

14, //opLogicalOr
15, //opLogicalAnd
16, //opLogicalXor

08, //opEquals
09, //opLesser
10, //opGreater
11, //opLEquals
12, //opGEquals
13 //opUnequals
);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengExpressionItem////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionItem.GetText: String;
begin
result := ''; // DUMMY
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionItem.GetValue: Variant;
begin
@@ -164,13 +200,11 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionItem.Create(const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionItem.Create(const aLine, aCol: Integer);
begin
inherited Create;
fOwner := aOwner;
fLine := aLine;
fCol := aCol;
fFilename := aFilename;
inherited Create(nil);
fLine := aLine;
fCol := aCol;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -188,9 +222,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionValue.Create(const aValue: Variant; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionValue.Create(const aValue: Variant; const aLine, aCol: Integer);
begin
inherited Create(aOwner, aLine, aCol, aFilename);
inherited Create(aLine, aCol);
fValue := aValue;
end;

@@ -209,9 +243,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionVariable.Create(const aName: String; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionVariable.Create(const aName: String; const aLine, aCol: Integer);
begin
inherited Create(aOwner, aLine, aCol, aFilename);
inherited Create(aLine, aCol);
fName := aName;
end;

@@ -234,9 +268,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
begin
inherited Create(aOwner, aLine, aCol, aFilename);
inherited Create(aLine, aCol);
fChild := aChild;
end;

@@ -247,8 +281,34 @@ begin
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengExpressionOperation///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionOperation.GetWeight: Integer;
begin
result := -1;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
begin
result := nil;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
begin
result := nil;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengExpressionUnaryOperation//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionUnaryOperation.GetWeight: Integer;
begin
result := UNARY_OPERATION_WEIGHTS[fUnaryOp];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionUnaryOperation.GetText: String;
begin
@@ -296,15 +356,29 @@ begin
raise EengInvalidParamter.Create(
ex.Message + '("' + GetText + '" ==> ' +
EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")',
Line, Col, Filename, Owner);
Line, Col, Filename, self);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
function TengExpressionUnaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
begin
result := fChild;
fChild := aItem;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionUnaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
begin
result := fChild;
fChild := aItem;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
begin
inherited Create(aOwner, aLine, aCol, aFilename);
fChild := nil;
inherited Create(aLine, aCol);
fChild := aChild;
fUnaryOp := aUnaryOp;
end;

@@ -317,6 +391,12 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengExpressionBinaryOperation/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionBinaryOperation.GetWeight: Integer;
begin
result := BINARY_OPERATION_WEIGHTS[fBinaryOp];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionBinaryOperation.GetText: String;
begin
@@ -367,17 +447,32 @@ begin
raise EengInvalidParamter.Create(
ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' +
EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")',
fLine, fCol, fFilename, fOwner);
self);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
function TengExpressionBinaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
begin
result := fFirst;
fFirst := aItem;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengExpressionBinaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
begin
inherited Create(aOwner, aLine, aCol, aFilename);
result := fSecond;
fSecond := aItem;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator;
const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
begin
inherited Create(aLine, aCol);
fBinaryOp := aOperator;
fFirst := nil;
fSecond := nil;
fFirst := aFirst;
fSecond := aSecond;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -394,240 +489,225 @@ end;
type
TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
TExpectedParams = set of TExpectedParam;
{$IFDEF USE_BITSPACE_UTILS}
TExpressionItemStack = specialize TutlSimpleList<TengExpressionItem>;
{$ELSE}
TExpressionItemStack = class(specialize TFPList<TengExpressionItem>)
public

TExpressionParser = class(TObject)
private
fParent: TengShaderPart;
fParamPos: Integer;
fParams: TengTokenParameterList;
private
function NextParam(var aParam: TengTokenParameter): Boolean;
function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
function Move(var aItem: TengExpressionItem): TengExpressionItem;
function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
function GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
private
function GetGroup: TengExpressionItem;
constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
end;
{$ENDIF}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ParseExpression(const aOwner: TObject; const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
var
p: TengTokenParameter;
//TExpressionParser/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.NextParam(var aParam: TengTokenParameter): Boolean;
begin
inc(fParamPos);
result := (fParamPos < fParams.Count);
if result then
aParam := fParams[fParamPos];
end;

procedure RaiseEx(const aMsg: String);
begin
raise EengExpression.Create(aMsg, p.Line, p.Col, aParam.Filename, aOwner);
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
begin
result := true;
for aOperator in TengExpressionUnaryOperator do
if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
exit;
result := false;
end;

function NextParam: Boolean;
begin
inc(aIndex);
result := (aIndex < aParam.Count);
if result then
p := aParam[aIndex];
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
begin
result := true;
for aOperator in TengExpressionBinaryOperator do
if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
exit;
result := false;
end;

function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
begin
result := true;
for aOperator in TengExpressionUnaryOperator do
if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
exit;
result := false;
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TExpressionParser.RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
begin
if (aName = '') then
aName := aParam.Name;
raise EengExpression.Create(aMsg + ' ' + aParam.Name, aParam.Line, aParam.Col, fParent.Filename, fParent);
end;

function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
begin
result := true;
for aOperator in TengExpressionBinaryOperator do
if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
exit;
result := false;
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.Move(var aItem: TengExpressionItem): TengExpressionItem;
begin
result := aItem;
aItem := nil;
end;

procedure MergeItems(const aStack: TExpressionItemStack; var aNew: TengExpressionItem);
var
item: TengExpressionItem;
begin
try
if (aStack.Count = 0) then begin
aStack.PushLast(aNew);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
var
o, n: TengExpressionOperation;
tmp: TengExpressionItem;
begin
result := nil;
try
if not Assigned(aOld) then begin
result := aNew;
exit;
end else if not Assigned(aNew) then begin
result := aOld;
exit;
end else if (aOld is TengExpressionOperation) and (aNew is TengExpressionOperation) then begin
o := (aOld as TengExpressionOperation);
n := (aNew as TengExpressionOperation);
if (n.Weight < o.Weight) then begin
tmp := n.ExchangeFirst(o.ExchangeLast(n));
aNew := nil;
exit;
end;

item := aStack.Last;
if (item is TengExpressionBinaryOperation) then begin
if (aNew is TengExpressionBinaryOperation) then begin
//both are binary operators, new is weaker then existing
if ((aNew as TengExpressionBinaryOperation).BinaryOp <
(item as TengExpressionBinaryOperation).BinaryOp) then
begin
(aNew as TengExpressionBinaryOperation).First := item;
aStack.PopLast;
aStack.PushLast(aNew);
aNew := nil;

//both are binary operators, new is stronger than existing
end else begin
if not Assigned((item as TengExpressionBinaryOperation).Second) then
RaiseEx('inconsistent state');
(aNew as TengExpressionBinaryOperation).First := (item as TengExpressionBinaryOperation).Second;
(item as TengExpressionBinaryOperation).Second := aNew;
aStack.PushLast(aNew);
aNew := nil;
end;

//existing is binary operator, new is normal
end else begin
if Assigned((item as TengExpressionBinaryOperation).Second) then
RaiseEx('inconsistent state');
(item as TengExpressionBinaryOperation).Second := aNew;
aNew := nil;
while (aStack.Count > 1) do
aStack.PopLast; //remove all but first
end;
result := aOld;
end else begin
//existing is normal item, new is binary operation
if (aNew is TengExpressionBinaryOperation) then begin
aStack.PopLast;
(aNew as TengExpressionBinaryOperation).First := item;
aStack.PushLast(aNew);
aNew := nil;

//existing is unary operation, new is normal item or unary operation
end else if (item is TengExpressionUnaryOperation) then begin
if Assigned((item as TengExpressionUnaryOperation).Child) then
RaiseEx('inconsistent state');
(item as TengExpressionUnaryOperation).Child := aNew;
if not (aNew is TengExpressionUnaryOperation) then begin
while (aStack.Count > 1) do
aStack.PopLast; //remove all but first
end else
aStack.PushLast(aNew);
aNew := nil;

//existing and new are both normal items
end else
RaiseEx('inconsistent state');
tmp := n.ExchangeFirst(o);
aOld := nil;
result := aNew;
end;
except
FreeAndNil(aNew);
raise;
end;
if Assigned(tmp) then
raise EengExpressionInternal.Create(1, fParent);
end else if (aOld is TengExpressionOperation) then begin
o := (aOld as TengExpressionOperation);
o.ExchangeLast(aNew);
aNew := nil;
result := aOld;
end else if (aNew is TengExpressionOperation) then begin
n := (aNew as TengExpressionOperation);
n.ExchangeFirst(aOld);
aOld := nil;
result := aNew;
end;;
except
FreeAndNil(aOld);
FreeAndNil(aNew);
result := nil;
raise;
end;
end;

function BuildTree(const aDepth: Integer = 0): TengExpressionItem;
var
uOp: TengExpressionUnaryOperator;
bOp: TengExpressionBinaryOperator;
expected: TExpectedParams;
stack: TExpressionItemStack;
l, c: Integer;
ei, tmp: TengExpressionItem;
begin
expected := [exVariable, exValue, exGroupBegin, exUnaryOperation];
result := nil;
stack := TExpressionItemStack.Create(false);
try try
repeat
// GroupBegin
if (p.Name = TOKEN_OP_GROUP_BEGIN) then begin
if not (exGroupBegin in expected) then
RaiseEx('unexpected ''' + p.Name + '''');
l := p.Line;
c := p.Col;
if not NextParam then
RaiseEx('unexpected end');
tmp := BuildTree(aDepth + 1);
ei := TengExpressionGroup.Create(tmp, aOwner, l, c, aParam.Filename);
try
MergeItems(stack, ei);
if (p.Name <> TOKEN_OP_GROUP_END) then
RaiseEx('missing ''' + TOKEN_OP_GROUP_END + '''');
expected := [exBinaryOperation, exGroupEnd];
except
FreeAndNil(ei);
raise;
end;

// GroupEnd
end else if (p.Name = TOKEN_OP_GROUP_END) then begin
if not (exGroupEnd in expected) or (aDepth = 0) then
RaiseEx('unexpected ''' + TOKEN_OP_GROUP_END + '''');
exit;

// UnaryOperation
end else if IsUnaryOperation(p.Name, uOp) then begin
if not (exUnaryOperation in expected) then
RaiseEx('unexpected operator: ' + p.Name);
ei := TengExpressionUnaryOperation.Create(uOp, aOwner, p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exVariable];
if (uOp <> opDefined) then
expected := expected + [exValue, exGroupBegin, exUnaryOperation]
except
FreeAndNil(ei);
raise;
end;

// BinaryOperation
end else if IsBinaryOperation(p.Name, bOp) then begin
if not (exBinaryOperation in expected) then
RaiseEx('unexpected operator: ' + p.Name);
ei := TengExpressionBinaryOperation.Create(bOp, aOwner, p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exVariable, exValue, exGroupBegin, exUnaryOperation];
except
FreeAndNil(ei);
raise;
end;

// Value
end else if p.Quoted and IsValidIdentifier(p.Name) then begin
if not (exValue in expected) then
RaiseEx('unexpected value: ' + p.Name);
ei := TengExpressionValue.Create(p.Name, aOwner,p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exGroupEnd, exBinaryOperation];
except
FreeAndNil(ei);
raise;
end;

// Variable
end else if IsValidIdentifier(p.Name) then begin
if not (exVariable in expected) then
RaiseEx('unexpected variable: ' + p.Name);
ei := TengExpressionVariable.Create(p.Name, aOwner, p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exGroupEnd, exBinaryOperation];
except
FreeAndNil(ei);
raise
end;

// Unknown
end else
RaiseEx('invalid parameter: ' + p.Name);
until not NextParam;
except
if (stack.Count > 0) then begin
stack[0].Free;
stack[0] := nil;
end;
raise;
end;
finally
if (stack.Count > 0) then
result := stack[0];
FreeAndNil(stack);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
var
uOp: TengExpressionUnaryOperator;
bOp: TengExpressionBinaryOperator;
item: TengExpressionItem;
param: TengTokenParameter;
begin
item := nil;
result := nil;
try
if NextParam(param) then begin
// GroupBegin
if (param.Name = TOKEN_OP_GROUP_BEGIN) then begin
if not (exGroupBegin in aExpected) then
RaiseEx('unexpected', param);
item := GetGroup;
result := TengExpressionGroup.Create(Move(item), param.Col, param.Line);

// GroupEnd
end else if (param.Name = TOKEN_OP_GROUP_END) then begin
if not (exGroupEnd in aExpected) then
RaiseEx('unexpected', param);

// UnaryOperation
end else if IsUnaryOperation(param.Name, uOp) then begin
if not (exUnaryOperation in aExpected) then
RaiseEx('unexpected operation:', param);
item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
result := TengExpressionUnaryOperation.Create(uOp, Move(item), param.Line, param.Col);

// BinaryOperation
end else if IsBinaryOperation(param.Name, bOp) then begin
if not (exBinaryOperation in aExpected) then
RaiseEx('unexpected operation:', param);
item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
item := TengExpressionBinaryOperation.Create(bOp, nil, Move(item), param.Line, param.Col);
result := Merge(result, item);

// Value
end else if param.Quoted and IsValidIdentifier(param.Name) then begin
if not (exValue in aExpected) then
RaiseEx('unexpected value:', param);
result := TengExpressionValue.Create(param.Name, param.Line, param.Col);

// Variable
end else if IsValidIdentifier(param.Name) then begin
if not (exVariable in aExpected) then
RaiseEx('unexpected variable:', param);
result := TengExpressionVariable.Create(param.Name, param.Line, param.Col);

// Unknown
end else
raise EengExpression.Create('invalid parameter: ' + param.Name, param.Line, param.Col, fParent.Filename, fParent);
end;

if not Assigned(result) and not (exGroupEnd in aExpected) then
RaiseEx('unexpected', param, 'end');
except
FreeAndNil(item);
FreeAndNil(result);
raise;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TExpressionParser.GetGroup: TengExpressionItem;
var
ex: TExpectedParams;
item: TengExpressionItem;
b: Boolean;
begin
dec(aIndex);
if not NextParam then with aParam[0] do
raise EengShaderPartInternal.Create('invalid parameter count in expression', Line, Col, aParam.Filename, aOwner);
result := BuildTree;
item := nil;
result := nil;
try
ex := [exVariable, exValue, exGroupBegin, exUnaryOperation];
repeat
item := GetExpr(ex);
b := Assigned(item);
result := Merge(result, Move(item));
ex := ex + [exBinaryOperation, exGroupEnd];
until not b;
except
FreeAndNil(result);
FreeAndNil(item);
raise;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TExpressionParser.Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
begin
fParamPos := aIndex - 1;
fParams := aParams;
fParent := aParent;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
var
parser: TExpressionParser;
begin
parser := TExpressionParser.Create(aParent, aParams, aIndex);
try
result := parser.GetGroup;
finally
FreeAndNil(parser);
end;
end;

end.

+ 46
- 1
uengShaderFileTypes.pas Voir le fichier

@@ -45,6 +45,10 @@ type
end;
EengShaderPartInternal = class(EengShaderPart);
EengExpression = class(EengShaderPart);
EengExpressionInternal = class(EengExpression)
ErrorCode: Integer;
constructor Create(const aErrorCode: Integer; const aSender: TObject);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengInvalidToken = class(EengShaderPartInternal)
@@ -127,11 +131,30 @@ type
constructor Create(const aName: String; const aNew, aOld: TObject; aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengUnknownIdentifier = class(EengShaderPart)
protected
function GenerateMessage: String; override;
public
Name: String;
constructor Create(const aName: String; const aSender: TObject); overload;
constructor Create(const aName: String; aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

implementation

uses
uengShaderPart;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengExpressionInternal////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengExpressionInternal.Create(const aErrorCode: Integer; const aSender: TObject);
begin
ErrorCode := aErrorCode;
inherited Create('internal error: ' + IntToStr(ErrorCode), aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -160,7 +183,7 @@ begin
p := (Sender as TengShaderPart);
aLines.Text := Message;
while Assigned(p) do begin
aLines.Add(Format('%s (%d:%d): %s', [p.Filename, p.Line, p.Col, GetName(p)]));
aLines.Add(Format(' %s (%d:%d): %s', [p.Filename, p.Line+1, p.Col, GetName(p)]));
p := p.Parent;
end;
end;
@@ -433,5 +456,27 @@ begin
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengUnknownIdentifier/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function EengUnknownIdentifier.GenerateMessage: String;
begin
result := 'unknown identifier: ' + Name;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengUnknownIdentifier.Create(const aName: String; const aSender: TObject);
begin
Name := aName;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengUnknownIdentifier.Create(const aName: String; aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
Name := aName;
inherited Create(aLine, aCol, aFilename, aSender);
end;

end.


+ 159
- 105
uengShaderPart.pas Voir le fichier

@@ -19,19 +19,25 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderFileSearchFlag = (
sfFirstOnly, // search first match only
sfEvaluateIf, // evaluate if statements before search and process with suitable subtree

sfSearchChildren, // search in children
sfSearchParents, // search in parents
sfSearchInherited, // search in inherited

sfCurrentFileOnly, // do not leave current file
sfCurrentScopeOnly, // do not leave current scopes
sfCurrentGeneratorOnly // do not leave current generator
TengSearchFlag = (
sfEvaluateIf, // evaluate if statements before search and process with suitable subtree
sfSearchAllIf, // search in all if sub trees

sfSearchPrevOnly, // search in previous items only
sfSearchInherited, // search in inherited

sfSearchChildren, // search in children
sfSearchChildrenLazy, // set sfSearchChildren in next recursion level
sfChildrenFileOnly, // do not leave current file when searching for children
sfChildrenGeneratorOnly, // do not leave current generator when searching for children
sfChildrenScopeOnly, // do not leave current scope when searching for children

sfSearchParents, // search in Parents
sfParentsFileOnly, // do not leave current file when searching in parents
sfParentsGeneratorOnly, // do not leave current generator when searching in parents
sfParentsScopeOnly // do not leave current scope when searching in parents
);
TengShaderFileSearchFlags = set of TengShaderFileSearchFlag;
TengSearchFlags = set of TengSearchFlag;

TengShaderPart = class;
CengShaderPart = class of TengShaderPart;
@@ -43,24 +49,34 @@ type
private
fOwner: TengShaderPart;
fPosition: Integer;
fReverse: Boolean;
function GetCurrent: TengShaderPart;
public
property Current: TengShaderPart read GetCurrent;
function GetEnumerator: TEnumerator;
function MoveNext: Boolean;
constructor Create(const aOwner: TengShaderPart);
constructor Create(const aOwner: TengShaderPart; const aReverse: Boolean = false);
end;

TSearchResults = class(specialize TutlHashSet<TengShaderPart>)
TSearchResults = class(specialize TutlList<TengShaderPart>)
private
fFirstOnly: Boolean;
fIgnore: TengShaderPart;
fTypes: array of CengShaderPart;
protected
function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; virtual;
public
constructor Create;
property FirstOnly: Boolean read fFirstOnly write fFirstOnly;
property Ignore: TengShaderPart read fIgnore write fIgnore;
function Add(const aPart: TengShaderPart): Boolean; reintroduce;
constructor Create(const aTypes: array of CengShaderPart);
end;

{ Code Loading & Storage }
private { members }
protected { members }
fParent: TengShaderPart;
fLine: Integer;
fCol: Integer;
protected
fRoot: TengShaderPart;
protected { virtual getter }
function GetCount: Integer; virtual;
@@ -69,12 +85,11 @@ type
function GetFilename: String; virtual;
function GetFileReader: IengShaderFileReader; virtual;
function GetFileWriter: IengShaderFileWriter; virtual;
protected { parse methodes }
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual;
public
function ParseText(const aArgs: TengParseArgs): String;

{ General }
protected
procedure UpdateCache; virtual;
function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; virtual;
public { general methods }
property Root: TengShaderPart read fRoot;
property Parent: TengShaderPart read fParent;
@@ -93,11 +108,10 @@ type
function GetParent(const aType: CengShaderPart; out aPart): Boolean;
function GetParent(const aType: CengShaderPart): TengShaderPart;

function FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart;
procedure FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchResults);
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults); virtual;
procedure Find(const aFlags: TengSearchFlags; const aResults: TSearchResults);

function GetEnumerator: TEnumerator;
function GetReverseEnumerator: TEnumerator;

constructor Create(const aParent: TengShaderPart); virtual;

@@ -108,7 +122,14 @@ type
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
end;

function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
TengShaderCodePart = class(TengShaderPart)
{ Code Loading & Storage }
protected
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual;
public
function ParseText(const aArgs: TengParseArgs): String;
end;
CengShaderCodePart = class of TengShaderCodePart;

implementation

@@ -116,50 +137,74 @@ uses
uengShaderPartScope, uengShaderCodeGenerator, uengShaderFile, uengShaderFileConstants;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
var
c: CengShaderPart;
function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
begin
result := true;
if (Length(aTypes) = 0) then
exit;
for c in aTypes do
if (aShaderPart is c) then
exit;
result := false;
result := fOwner[fPosition];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
function TengShaderPart.TEnumerator.GetEnumerator: TEnumerator;
begin
result := fOwner[fPosition];
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.TEnumerator.MoveNext: Boolean;
begin
inc(fPosition);
result := (fPosition < fOwner.Count);
if not fReverse
then inc(fPosition)
else dec(fPosition);
result := (0 <= fPosition) and (fPosition < fOwner.Count);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart);
constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart; const aReverse: Boolean);
begin
inherited Create;
fOwner := aOwner;
fPosition := -1;
fReverse := aReverse;
if not fReverse
then fPosition := -1
else fPosition := aOwner.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPart.TSearchResults/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.TSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean;
var
c: CengShaderPart;
begin
aContinue := not fFirstOnly or (Count = 0);;
if aContinue then begin
result := (Length(fTypes) = 0);
for c in fTypes do
result := result or (aPart is c);
result := result and (aPart <> fIgnore);
end else
result := false;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPart.TSearchResults////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.TSearchResults.Add(const aPart: TengShaderPart): Boolean;
begin
result := true;
if result and CheckObj(aPart, result) then
inherited Add(aPart);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderPart.TSearchResults.Create;
constructor TengShaderPart.TSearchResults.Create(const aTypes: array of CengShaderPart);
var
i: Integer;
begin
inherited Create(false);
fFirstOnly := false;
SetLength(fTypes, Length(aTypes));
for i := Low(fTypes) to High(fTypes) do
fTypes[i] := aTypes[i];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -207,26 +252,49 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.ParseText(const aArgs: TengParseArgs): String;
procedure TengShaderPart.UpdateCache;
var
params: TengTokenParameterList;
p: TengShaderPart;
begin
params := TengTokenParameterList.Create(Filename);
try
fCol := aArgs.Col;
fLine := aArgs.Line;
if (GetTokenName <> '') then
aArgs.ExtractToken(self, params);
result := ParseIntern(aArgs, params);
finally
FreeAndNil(params);
end;
for p in self do
p.UpdateCache;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean;
var
c: TengShaderPart;
b: Boolean;
begin
result := ''; // DUMMY
b := false;
result := true;
if (sfSearchChildren in aFlags) then begin
for c in self.GetReverseEnumerator do begin
b := b or (c = aChild);
if (sfSearchPrevOnly in aFlags) and not b then
continue;
if (c <> aChild) and
(not (sfChildrenScopeOnly in aFlags) or not (c is TengShaderPartScope)) and
(not (sfChildrenGeneratorOnly in aFlags) or not (c is TengShaderCodeGenerator)) and
(not (sfChildrenFileOnly in aFlags) or not (c is TengShaderFile))
then
result := result and c.FindIntern(aFlags - [sfSearchParents], nil, aResults);
if not result then
exit;
end;
end;

result := result and aResults.Add(self);

if (sfSearchChildrenLazy in aFlags) then
aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy];
if (sfSearchParents in aFlags) and
Assigned(Parent) and
(not (sfParentsScopeOnly in aFlags) or not (self is TengShaderPartScope)) and
(not (sfParentsGeneratorOnly in aFlags) or not (self is TengShaderCodeGenerator)) and
(not (sfParentsFileOnly in aFlags) or not (self is TengShaderFile))
then
result := result and Parent.FindIntern(aFlags, self, aResults);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -257,60 +325,21 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart;
var
l: TSearchResults;
procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TSearchResults);
begin
l := TSearchResults.Create;
try
FindIntern(aFlags + [sfFirstOnly], 0, aTypes, l);
if (l.Count > 0)
then result := l[0]
else result := nil;
finally
FreeAndNil(l);
end;
FindIntern(aFlags, nil, aResults);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPart.FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchResults);
begin
FindIntern(aFlags, 0, aTypes, aList);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPart.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults);
var
c: TengShaderPart;
function TengShaderPart.GetEnumerator: TEnumerator;
begin
if (sfFirstOnly in aFlags) and (aList.Count > 0) then
exit;

if (sfSearchChildren in aFlags) then begin
for c in self do
if (not (sfCurrentScopeOnly in aFlags) or not (c is TengShaderPartScope)) and
(not (sfCurrentFileOnly in aFlags) or not (c is TengShaderFile)) and
(not (sfCurrentGeneratorOnly in aFlags) or not (c is TengShaderCodeGenerator))
then
c.FindIntern(aFlags, aDepth+1, aTypes, aList);
end;

if CheckType(self, aTypes) then
aList.Add(self);

if (sfSearchParents in aFlags) and
Assigned(Parent) and
(not (sfCurrentScopeOnly in aFlags) or not (self is TengShaderPartScope)) and
(not (sfCurrentFileOnly in aFlags) or not (self is TengShaderFile)) and
(not (sfCurrentGeneratorOnly in aFlags) or not (self is TengShaderCodeGenerator))
then
Parent.FindIntern(aFlags, aDepth-1, aTypes, aList);
result := TEnumerator.Create(self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.GetEnumerator: TEnumerator;
function TengShaderPart.GetReverseEnumerator: TEnumerator;
begin
result := TEnumerator.Create(self);
result := TEnumerator.Create(self, true);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -341,5 +370,30 @@ begin
// DUMMY
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderCodePart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodePart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
result := ''; // DUMMY
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodePart.ParseText(const aArgs: TengParseArgs): String;
var
params: TengTokenParameterList;
begin
params := TengTokenParameterList.Create(Filename);
try
fCol := aArgs.Col;
fLine := aArgs.Line;
if (GetTokenName <> '') then
aArgs.ExtractToken(self, params);
result := ParseIntern(aArgs, params);
finally
FreeAndNil(params);
end;
end;

end.


+ 1
- 1
uengShaderPartCall.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartCall = class(TengShaderPart)
TengShaderPartCall = class(TengShaderCodePart)
{ Code Loading & Storage }
private { member }
fName: String;


+ 32
- 0
uengShaderPartClass.pas Voir le fichier

@@ -28,6 +28,8 @@ type
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ General }
protected
procedure UpdateInherited; override;
public
property Name: String read fName;
property Extends: TStrings read GetExtends;
@@ -97,6 +99,36 @@ begin
result := CheckEndToken(aArgs, self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartClass.UpdateInherited;
var
sr: TengShaderPart.TSearchResults;
i: Integer;
s: String;
begin
inherited UpdateInherited;
fInherited.Clear;
sr := TengShaderPart.TSearchResults.Create([TengShaderPartClass]);
try
sr.Ignore := self;
Find([sfSearchChildrenLazy, sfSearchParents, sfParentsFileOnly, sfSearchPrevOnly], sr);
for s in fExtends do begin
i := 0;
while (i >= 0) and (i < sr.Count) do begin
if ((sr[i] as TengShaderPartClass).Name = s) then begin
fInherited.Add(sr[i]);
i := -1;
end;
inc(i);
end;
if (i > 0) or (sr.Count = 0) then
raise EengUnknownIdentifier.Create(s, self);
end;
finally
FreeAndNil(sr);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderPartClass.Create(const aParent: TengShaderPart);
begin


+ 4
- 4
uengShaderPartCntr.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartCntr = class(TengShaderPart)
TengShaderPartCntr = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fChildren: TengShaderPartList;
@@ -36,7 +36,7 @@ uses
uengShaderPartInclude, uengShaderPartParameter, uengShaderPartComment;

const
TOKEN_CLASSES: array[0..20] of CengShaderPart = (
TOKEN_CLASSES: array[0..20] of CengShaderCodePart = (
TengShaderPartCall,
TengShaderPartClass,
TengShaderPartDefine,
@@ -73,8 +73,8 @@ end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartCntr.HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
var
p: TengShaderPart;
c: CengShaderPart;
p: TengShaderCodePart;
c: CengShaderCodePart;
begin
p := nil;
for c in TOKEN_CLASSES do begin


+ 1
- 1
uengShaderPartComment.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartComment = class(TengShaderPart)
TengShaderPartComment = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fText: String;


+ 1
- 1
uengShaderPartEcho.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartEcho = class(TengShaderPart)
TengShaderPartEcho = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fName: String;


+ 20
- 18
uengShaderPartIf.pas Voir le fichier

@@ -11,12 +11,12 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartIf = class(TengShaderPart)
TengShaderPartIf = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fExpression: TengExpressionItem;
fIfPart: TengShaderPart;
fElsePart: TengShaderPart;
fIfPart: TengShaderCodePart;
fElsePart: TengShaderCodePart;
function HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
protected
function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; virtual;
@@ -26,8 +26,9 @@ type
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ General }
protected
function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; override;
public
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults); override;
destructor Destroy; override;

{ Class Methods }
@@ -67,12 +68,12 @@ uses
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartIf.HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
const
TOKEN_CLASSES: array[0..1] of CengShaderPart = (
TOKEN_CLASSES: array[0..1] of CengShaderCodePart = (
TengShaderPartElse,
TengShaderPartElIf
);
var
c: CengShaderPart;
c: CengShaderCodePart;
begin
for c in TOKEN_CLASSES do begin
if c.CheckToken(aToken) then begin
@@ -114,7 +115,7 @@ end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartIf.GetText: String;
begin
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fExpression.GetText + TOKEN_CHAR_END + fIfPart.Text;
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fExpression.Text + TOKEN_CHAR_END + fIfPart.Text;
if Assigned(fElsePart) then
result := result + fElsePart.Text;
result := result + TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END;
@@ -136,20 +137,21 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartIf.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults);
function TengShaderPartIf.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean;
begin
if (sfEvaluateIf in aFlags) then begin
inherited FindIntern(aFlags - [sfSearchChildren], aDepth, aTypes, aList);
if (sfSearchChildren in aFlags) then begin
if fExpression.GetValue then begin
if Assigned(fIfPart) then
fIfPart.FindIntern(aFlags, aDepth, aTypes, aList);
end else begin
if Assigned(fElsePart) then
fElsePart.FindIntern(aFlags, aDepth, aTypes, aList);
end;
result := true;
if (sfEvaluateIf in aFlags) and (sfSearchChildren in aFlags) then begin
if fExpression.GetValue then begin
if Assigned(fIfPart) then
fIfPart.Find(aFlags, aResults);
end else begin
if Assigned(fElsePart) then
fElsePart.Find(aFlags, aResults);
end;
end;
if not (sfSearchAllIf in aFlags) then
exclude(aFlags, sfSearchChildren);
result := result and inherited FindIntern(aFlags, aChild, aResults);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 1
- 1
uengShaderPartInclude.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartInclude = class(TengShaderPart)
TengShaderPartInclude = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fShaderFile: TengShaderFile;


+ 1
- 21
uengShaderPartKeyValuePair.pas Voir le fichier

@@ -16,7 +16,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartKeyValuePair = class(TengShaderPart)
TengShaderPartKeyValuePair = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fName: String;
@@ -38,7 +38,6 @@ type
{ Class Methods }
public
class function GetTokenName: String; override;
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
end;
TengShaderPartPropertyMap = specialize TutlMap<string, TengShaderPartProperty>;

@@ -102,25 +101,6 @@ begin
result := TOKEN_PROPERTY;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class procedure TengShaderPartProperty.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);

procedure RaiseEx(const aToken: String);
begin
with aArgs do
raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed in ' + aToken, Line, Col, Filename, aParent);
end;

begin
inherited Validate(aArgs, aParent);
if aParent.HasParent(TengShaderPartElIf, true) then
RaiseEx(TengShaderPartElIf.GetTokenName);
if aParent.HasParent(TengShaderPartElse, true) then
RaiseEx(TengShaderPartElse.GetTokenName);
if aParent.HasParent(TengShaderPartIf, true) then
RaiseEx(TengShaderPartIf.GetTokenName);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartDefine//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 1
- 1
uengShaderPartMessage.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartMessage = class(TengShaderPart)
TengShaderPartMessage = class(TengShaderCodePart)

end;



+ 1
- 1
uengShaderPartMeta.pas Voir le fichier

@@ -33,7 +33,7 @@ type
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartMeta = class(TengShaderPart)
TengShaderPartMeta = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fData: TengMetaData;


+ 1
- 1
uengShaderPartParameter.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartParameter = class(TengShaderPart)
TengShaderPartParameter = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fName: String;


+ 0
- 9
uengShaderPartProc.pas Voir le fichier

@@ -46,7 +46,6 @@ type
{ Class Members }
public
class function GetTokenName: String; override;
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -171,14 +170,6 @@ begin
result := TOKEN_PROC;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class procedure TengShaderPartProc.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
begin
if (aParent.HasParent(TengShaderPartProc, true)) then with aArgs do
raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed inside ' +
TOKEN_PROC + ', ' + TOKEN_FUNC + ' or + ' + TOKEN_MAIN, Line, Col, aParent.Filename, aParent);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartMain////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 3
- 3
uengShaderPartText.pas Voir le fichier

@@ -11,7 +11,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartText = class(TengShaderPart)
TengShaderPartText = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fText: String;
@@ -25,7 +25,7 @@ type
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartLineBreak = class(TengShaderPart)
TengShaderPartLineBreak = class(TengShaderCodePart)
{ Code Loading & Storage }
protected
function GetText: String; override;
@@ -37,7 +37,7 @@ type
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartCommandEnd = class(TengShaderPart)
TengShaderPartCommandEnd = class(TengShaderCodePart)
{ Code Loading & Storage }
private
fToken: String;


Chargement…
Annuler
Enregistrer