unit uengShaderPart; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, SysUtils, uengShaderFileParser, uengShaderFileTypes {$IFDEF USE_BITSPACE_UTILS} , uutlGenerics {$ELSE} , fgl {$ENDIF} ; 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 ); TengShaderFileSearchFlags = set of TengShaderFileSearchFlag; TengShaderPart = class; CengShaderPart = class of TengShaderPart; TengShaderPartList = specialize TutlSimpleList; TengShaderPart = class(TIntfObjNoRefCount) { Nested Types } public type TEnumerator = class(TObject) private fOwner: TengShaderPart; fPosition: Integer; function GetCurrent: TengShaderPart; public property Current: TengShaderPart read GetCurrent; function MoveNext: Boolean; constructor Create(const aOwner: TengShaderPart); end; TSearchResults = class(specialize TutlHashSet) public constructor Create; end; { Code Loading & Storage } private { members } fParent: TengShaderPart; fLine: Integer; fCol: Integer; protected fRoot: TengShaderPart; 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; protected { parse methodes } function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual; public function ParseText(const aArgs: TengParseArgs): String; { General } 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; 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; function GetEnumerator: 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; function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; implementation uses uengShaderPartScope, uengShaderCodeGenerator, uengShaderFile, uengShaderFileConstants; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; var c: CengShaderPart; begin result := true; if (Length(aTypes) = 0) then exit; for c in aTypes do if (aShaderPart is c) then exit; result := false; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart; begin result := fOwner[fPosition]; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.TEnumerator.MoveNext: Boolean; begin inc(fPosition); result := (fPosition < fOwner.Count); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart); begin inherited Create; fOwner := aOwner; fPosition := -1; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart.TSearchResults//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPart.TSearchResults.Create; begin inherited Create(false); 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.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; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; begin result := ''; // DUMMY 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; 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; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart; var l: 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; 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; 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); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetEnumerator: TEnumerator; begin result := TEnumerator.Create(self); 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; end.