|
- unit uengShaderPart;
-
- {$mode objfpc}{$H+}
- {$I uengShaderFile.inc}
-
- interface
-
- uses
- Classes, SysUtils,
-
- uengShaderFileParser, uengShaderFileTypes
-
- {$IFDEF USE_BITSPACE_UTILS}
- , uutlGenerics
- {$ELSE}
- , fgl
- {$ENDIF}
- ;
-
- type
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- 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
- sfChildrenOnlyFile, // do not leave current file when searching for children
- sfChildrenOnlyClass, // do not leave current class when searching for children
- sfChildrenOnlyGenerator, // do not leave current generator when searching for children
- sfChildrenOnlyScope, // do not leave current scope when searching for children
- sfChildrenForceFile, // overwrite sfChildrenOnlyXXX flag when item is a file
- sfChildrenForceClass, // overwrite sfChildrenOnlyXXX flag when item is a class
- sfChildrenForceGenerator, // overwrite sfChildrenOnlyXXX flag when item is a generator
- sfChildrenForceScope, // overwrite sfChildrenOnlyXXX flag when item is a scope
-
- sfSearchParents, // search in Parents
- sfParentsOnlyFile, // do not leave current file when searching in parents
- sfParentsOnlyClass, // do not leave current class when searching in parents
- sfParentsOnlyGenerator, // do not leave current generator when searching in parents
- sfParentsOnlyScope, // do not leave current scope when searching in parents
- sfParentsForceFile, // overwrite sfParentsOnlyXXX flag when item is a file
- sfParentsForceClass, // overwrite sfParentsOnlyXXX flag when item is a class
- sfParentsForceGenerator, // overwrite sfParentsOnlyXXX flag when item is a generator
- sfParentsForceScope // overwrite sfParentsOnlyXXX flag when item is a scope
- );
- TengSearchFlags = set of TengSearchFlag;
-
- const
- SEARCH_FLAG_CURRENT_SCOPE = [
- sfSearchPrevOnly,
- sfSearchInherited,
- sfSearchChildrenLazy,
- sfChildrenOnlyScope,
- sfChildrenForceFile,
- sfSearchParents,
- sfParentsOnlyFile
- ];
- SEARCH_FLAG_CLASS_PROPERTIES = [
- sfSearchAllIf,
- sfSearchChildren,
- sfChildrenOnlyGenerator,
- sfChildrenForceFile
- ];
- SEARCH_FLAG_FILE_PROPERTIES = [
- sfSearchAllIf,
- sfSearchChildren,
- sfChildrenOnlyGenerator
- ];
-
- type
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengShaderPart = class;
- CengShaderPart = class of TengShaderPart;
- TengShaderPartList = specialize TutlSimpleList<TengShaderPart>;
-
- TengSearchResults = 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
- 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;
-
- TengShaderPart = class(TIntfObjNoRefCount)
- { Nested Types }
- public type
- TEnumerator = class(TObject)
- 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; const aReverse: Boolean = false);
- end;
-
- { Code Loading & Storage }
- protected { members }
- fRoot: TengShaderPart;
- fParent: TengShaderPart;
- fLine: Integer;
- fCol: Integer;
- protected { virtual getter }
- function GetCount: Integer; virtual;
- function GetChild(const aIndex: Integer): TengShaderPart; virtual;
- function GetText: String; virtual;
- function GetFilename: String; virtual;
- function GetFileReader: IengShaderFileReader; virtual;
- function GetFileWriter: IengShaderFileWriter; virtual;
-
- { General }
- protected
- function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; virtual;
- procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); virtual;
- public { general methods }
- property Root: TengShaderPart read fRoot;
- property Parent: TengShaderPart read fParent;
- property Line: Integer read fLine;
- property Col: Integer read fCol;
- property Filename: String read GetFilename;
- property Text: String read GetText;
- property Count: Integer read GetCount;
-
- property FileReader: IengShaderFileReader read GetFileReader;
- property FileWriter: IengShaderFileWriter read GetFileWriter;
-
- property Children[const aIndex: Integer]: TengShaderPart read GetChild; default;
-
- function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean;
- function GetParent(const aType: CengShaderPart; out aPart): Boolean;
- function GetParent(const aType: CengShaderPart): TengShaderPart;
-
- procedure Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults);
- procedure PrintTrace(const aPrefix: String; const aLines: TStrings);
- procedure LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
-
- function GetEnumerator: TEnumerator;
- function GetReverseEnumerator: TEnumerator;
-
- constructor Create(const aParent: TengShaderPart); virtual;
-
- { Class Methods }
- public
- class function GetTokenName: String; virtual;
- class function CheckToken(const aToken: String): Boolean; virtual;
- class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
- end;
-
- 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
-
- uses
- uengShaderPartScope, uengShaderCodeGenerator, uengShaderPartClass, uengShaderFile, uengShaderFileConstants;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
- begin
- result := fOwner[fPosition];
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.TEnumerator.GetEnumerator: TEnumerator;
- begin
- result := self;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.TEnumerator.MoveNext: Boolean;
- begin
- if not fReverse
- then inc(fPosition)
- else dec(fPosition);
- result := (0 <= fPosition) and (fPosition < fOwner.Count);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart; const aReverse: Boolean);
- begin
- inherited Create;
- fOwner := aOwner;
- fReverse := aReverse;
- if not fReverse
- then fPosition := -1
- else fPosition := aOwner.Count;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengSearchResults/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengSearchResults.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;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengSearchResults.Add(const aPart: TengShaderPart): Boolean;
- begin
- result := true;
- if result and CheckObj(aPart, result) then
- inherited Add(aPart);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengSearchResults.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;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetCount: Integer;
- begin
- result := 0;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart;
- begin
- EengShaderPartInternal.Create('this part does not have any children');
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetText: String;
- begin
- result := ''; //DUMMY
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetFilename: String;
- begin
- if Assigned(fParent)
- then result := fParent.Filename
- else result := UNKNOWN_FILENAME;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetFileReader: IengShaderFileReader;
- begin
- if Assigned(fParent)
- then result := fParent.GetFileReader
- else result := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetFileWriter: IengShaderFileWriter;
- begin
- if Assigned(fParent)
- then result := fParent.GetFileWriter
- else result := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean;
-
- function VisitChild(const aItem: TengShaderPart): Boolean;
- begin
- result := (sfSearchChildren in aFlags);
- if not result then
- exit;
- result := result and
- Assigned(aItem) and
- (not (sfChildrenOnlyFile in aFlags) or not (aItem is TengShaderFile)) and
- (not (sfChildrenOnlyClass in aFlags) or not (aItem is TengShaderPartClass)) and
- (not (sfChildrenOnlyGenerator in aFlags) or not (aItem is TengShaderCodeGenerator)) and
- (not (sfChildrenOnlyScope in aFlags) or not (aItem is TengShaderPartScope));
- result := result or
- ((sfChildrenForceFile in aFlags) and (aItem is TengShaderFile)) or
- ((sfChildrenForceClass in aFlags) and (aItem is TengShaderPartClass)) or
- ((sfChildrenForceGenerator in aFlags) and (aItem is TengShaderCodeGenerator)) or
- ((sfChildrenForceScope in aFlags) and (aItem is TengShaderPartScope));
- end;
-
- function VisitParent: Boolean;
- begin
- result := (sfSearchParents in aFlags);
- if not result then
- exit;
- result := result and
- (not (sfParentsOnlyFile in aFlags) or not (self is TengShaderFile)) and
- (not (sfParentsOnlyClass in aFlags) or not (self is TengShaderPartClass)) and
- (not (sfParentsOnlyGenerator in aFlags) or not (self is TengShaderCodeGenerator)) and
- (not (sfParentsOnlyScope in aFlags) or not (self is TengShaderPartScope));
- result := result or
- ((sfParentsForceFile in aFlags) and (self is TengShaderFile)) or
- ((sfParentsForceClass in aFlags) and (self is TengShaderPartClass)) or
- ((sfParentsForceGenerator in aFlags) and (self is TengShaderCodeGenerator)) or
- ((sfParentsForceScope in aFlags) and (self is TengShaderPartScope));
- end;
-
- var
- c: TengShaderPart;
- b: Boolean;
- begin
- 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) then begin
- result := result and aResults.Add(c);
- if VisitChild(c) then
- result := result and c.FindIntern(aFlags - [sfSearchParents, sfSearchPrevOnly], nil, aResults);
- end;
- if not result then
- exit;
- end;
- end;
-
- if (sfSearchChildrenLazy in aFlags) then
- aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy];
- if (sfSearchParents in aFlags) and Assigned(Parent) then begin
- if VisitParent then
- result := result and Parent.FindIntern(aFlags, self, aResults);
- result := result and aResults.Add(Parent);
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TengShaderPart.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
- begin
- if Assigned(Parent) then
- Parent.LogMsgIntern(aSender, aLogLevel, aMsg);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean;
- var
- p: TengShaderPart;
- begin
- result := (aIncludeSelf and (self is aType)) or GetParent(aType, p);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean;
- begin
- result := true;
- TengShaderPart(aPart) := nil;
- if (fParent is aType) then
- TengShaderPart(aPart) := fParent
- else if Assigned(fParent) then
- result := fParent.GetParent(aType, aPart)
- else
- result := false;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
- begin
- if not GetParent(aType, result) then
- raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults);
- begin
- FindIntern(aFlags, nil, aResults);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TengShaderPart.PrintTrace(const aPrefix: String; const aLines: TStrings);
-
- function GetName(const aPart: TengShaderPart): String;
- begin
- result := aPart.GetTokenName;
- if (result = '')
- then result := aPart.ClassName
- else result := result + ' (' + aPart.ClassName + ')';
- end;
-
- var
- p: TengShaderPart;
- begin
- p := self;
- while Assigned(p) do begin
- aLines.Add(Format('%s%s (%d:%d): %s', [aPrefix, p.Filename, p.Line+1, p.Col, GetName(p)]));
- p := p.Parent;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TengShaderPart.LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
- begin
- LogMsgIntern(self, aLogLevel, aMsg);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetEnumerator: TEnumerator;
- begin
- result := TEnumerator.Create(self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengShaderPart.GetReverseEnumerator: TEnumerator;
- begin
- result := TEnumerator.Create(self, true);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengShaderPart.Create(const aParent: TengShaderPart);
- begin
- inherited Create;
- fParent := aParent;
- if Assigned(fParent)
- then fRoot := fParent.Root
- else fRoot := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- class function TengShaderPart.GetTokenName: String;
- begin
- result := ''; // DUMMY
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- class function TengShaderPart.CheckToken(const aToken: String): Boolean;
- begin
- result := (aToken = GetTokenName);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
- 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.
|