您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

400 行
16 KiB

  1. unit uengShaderPart;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderFileParser, uengShaderFileTypes
  8. {$IFDEF USE_BITSPACE_UTILS}
  9. , uutlGenerics
  10. {$ELSE}
  11. , fgl
  12. {$ENDIF}
  13. ;
  14. type
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. TengSearchFlag = (
  17. sfEvaluateIf, // evaluate if statements before search and process with suitable subtree
  18. sfSearchAllIf, // search in all if sub trees
  19. sfSearchPrevOnly, // search in previous items only
  20. sfSearchInherited, // search in inherited
  21. sfSearchChildren, // search in children
  22. sfSearchChildrenLazy, // set sfSearchChildren in next recursion level
  23. sfChildrenFileOnly, // do not leave current file when searching for children
  24. sfChildrenGeneratorOnly, // do not leave current generator when searching for children
  25. sfChildrenScopeOnly, // do not leave current scope when searching for children
  26. sfSearchParents, // search in Parents
  27. sfParentsFileOnly, // do not leave current file when searching in parents
  28. sfParentsGeneratorOnly, // do not leave current generator when searching in parents
  29. sfParentsScopeOnly // do not leave current scope when searching in parents
  30. );
  31. TengSearchFlags = set of TengSearchFlag;
  32. TengShaderPart = class;
  33. CengShaderPart = class of TengShaderPart;
  34. TengShaderPartList = specialize TutlSimpleList<TengShaderPart>;
  35. TengShaderPart = class(TIntfObjNoRefCount)
  36. { Nested Types }
  37. public type
  38. TEnumerator = class(TObject)
  39. private
  40. fOwner: TengShaderPart;
  41. fPosition: Integer;
  42. fReverse: Boolean;
  43. function GetCurrent: TengShaderPart;
  44. public
  45. property Current: TengShaderPart read GetCurrent;
  46. function GetEnumerator: TEnumerator;
  47. function MoveNext: Boolean;
  48. constructor Create(const aOwner: TengShaderPart; const aReverse: Boolean = false);
  49. end;
  50. TSearchResults = class(specialize TutlList<TengShaderPart>)
  51. private
  52. fFirstOnly: Boolean;
  53. fIgnore: TengShaderPart;
  54. fTypes: array of CengShaderPart;
  55. protected
  56. function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; virtual;
  57. public
  58. property FirstOnly: Boolean read fFirstOnly write fFirstOnly;
  59. property Ignore: TengShaderPart read fIgnore write fIgnore;
  60. function Add(const aPart: TengShaderPart): Boolean; reintroduce;
  61. constructor Create(const aTypes: array of CengShaderPart);
  62. end;
  63. { Code Loading & Storage }
  64. protected { members }
  65. fParent: TengShaderPart;
  66. fLine: Integer;
  67. fCol: Integer;
  68. fRoot: TengShaderPart;
  69. protected { virtual getter }
  70. function GetCount: Integer; virtual;
  71. function GetChild(const aIndex: Integer): TengShaderPart; virtual;
  72. function GetText: String; virtual;
  73. function GetFilename: String; virtual;
  74. function GetFileReader: IengShaderFileReader; virtual;
  75. function GetFileWriter: IengShaderFileWriter; virtual;
  76. { General }
  77. protected
  78. procedure UpdateCache; virtual;
  79. function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; virtual;
  80. public { general methods }
  81. property Root: TengShaderPart read fRoot;
  82. property Parent: TengShaderPart read fParent;
  83. property Line: Integer read fLine;
  84. property Col: Integer read fCol;
  85. property Filename: String read GetFilename;
  86. property Text: String read GetText;
  87. property Count: Integer read GetCount;
  88. property FileReader: IengShaderFileReader read GetFileReader;
  89. property FileWriter: IengShaderFileWriter read GetFileWriter;
  90. property Children[const aIndex: Integer]: TengShaderPart read GetChild; default;
  91. function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean;
  92. function GetParent(const aType: CengShaderPart; out aPart): Boolean;
  93. function GetParent(const aType: CengShaderPart): TengShaderPart;
  94. procedure Find(const aFlags: TengSearchFlags; const aResults: TSearchResults);
  95. function GetEnumerator: TEnumerator;
  96. function GetReverseEnumerator: TEnumerator;
  97. constructor Create(const aParent: TengShaderPart); virtual;
  98. { Class Methods }
  99. public
  100. class function GetTokenName: String; virtual;
  101. class function CheckToken(const aToken: String): Boolean; virtual;
  102. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
  103. end;
  104. TengShaderCodePart = class(TengShaderPart)
  105. { Code Loading & Storage }
  106. protected
  107. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual;
  108. public
  109. function ParseText(const aArgs: TengParseArgs): String;
  110. end;
  111. CengShaderCodePart = class of TengShaderCodePart;
  112. implementation
  113. uses
  114. uengShaderPartScope, uengShaderCodeGenerator, uengShaderFile, uengShaderFileConstants;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. //TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
  119. begin
  120. result := fOwner[fPosition];
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. function TengShaderPart.TEnumerator.GetEnumerator: TEnumerator;
  124. begin
  125. result := self;
  126. end;
  127. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. function TengShaderPart.TEnumerator.MoveNext: Boolean;
  129. begin
  130. if not fReverse
  131. then inc(fPosition)
  132. else dec(fPosition);
  133. result := (0 <= fPosition) and (fPosition < fOwner.Count);
  134. end;
  135. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  136. constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart; const aReverse: Boolean);
  137. begin
  138. inherited Create;
  139. fOwner := aOwner;
  140. fReverse := aReverse;
  141. if not fReverse
  142. then fPosition := -1
  143. else fPosition := aOwner.Count;
  144. end;
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. //TengShaderPart.TSearchResults/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. function TengShaderPart.TSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean;
  149. var
  150. c: CengShaderPart;
  151. begin
  152. aContinue := not fFirstOnly or (Count = 0);;
  153. if aContinue then begin
  154. result := (Length(fTypes) = 0);
  155. for c in fTypes do
  156. result := result or (aPart is c);
  157. result := result and (aPart <> fIgnore);
  158. end else
  159. result := false;
  160. end;
  161. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. function TengShaderPart.TSearchResults.Add(const aPart: TengShaderPart): Boolean;
  163. begin
  164. result := true;
  165. if result and CheckObj(aPart, result) then
  166. inherited Add(aPart);
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. constructor TengShaderPart.TSearchResults.Create(const aTypes: array of CengShaderPart);
  170. var
  171. i: Integer;
  172. begin
  173. inherited Create(false);
  174. fFirstOnly := false;
  175. SetLength(fTypes, Length(aTypes));
  176. for i := Low(fTypes) to High(fTypes) do
  177. fTypes[i] := aTypes[i];
  178. end;
  179. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  180. //TengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. function TengShaderPart.GetCount: Integer;
  183. begin
  184. result := 0;
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart;
  188. begin
  189. EengShaderPartInternal.Create('this part does not have any children');
  190. end;
  191. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  192. function TengShaderPart.GetText: String;
  193. begin
  194. result := ''; //DUMMY
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. function TengShaderPart.GetFilename: String;
  198. begin
  199. if Assigned(fParent)
  200. then result := fParent.Filename
  201. else result := UNKNOWN_FILENAME;
  202. end;
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. function TengShaderPart.GetFileReader: IengShaderFileReader;
  205. begin
  206. if Assigned(fParent)
  207. then result := fParent.GetFileReader
  208. else result := nil;
  209. end;
  210. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. function TengShaderPart.GetFileWriter: IengShaderFileWriter;
  212. begin
  213. if Assigned(fParent)
  214. then result := fParent.GetFileWriter
  215. else result := nil;
  216. end;
  217. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. procedure TengShaderPart.UpdateCache;
  219. var
  220. p: TengShaderPart;
  221. begin
  222. for p in self do
  223. p.UpdateCache;
  224. end;
  225. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  226. function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean;
  227. var
  228. c: TengShaderPart;
  229. b: Boolean;
  230. begin
  231. b := false;
  232. result := true;
  233. if (sfSearchChildren in aFlags) then begin
  234. for c in self.GetReverseEnumerator do begin
  235. b := b or (c = aChild);
  236. if (sfSearchPrevOnly in aFlags) and not b then
  237. continue;
  238. if (c <> aChild) and
  239. (not (sfChildrenScopeOnly in aFlags) or not (c is TengShaderPartScope)) and
  240. (not (sfChildrenGeneratorOnly in aFlags) or not (c is TengShaderCodeGenerator)) and
  241. (not (sfChildrenFileOnly in aFlags) or not (c is TengShaderFile))
  242. then
  243. result := result and c.FindIntern(aFlags - [sfSearchParents], nil, aResults);
  244. if not result then
  245. exit;
  246. end;
  247. end;
  248. result := result and aResults.Add(self);
  249. if (sfSearchChildrenLazy in aFlags) then
  250. aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy];
  251. if (sfSearchParents in aFlags) and
  252. Assigned(Parent) and
  253. (not (sfParentsScopeOnly in aFlags) or not (self is TengShaderPartScope)) and
  254. (not (sfParentsGeneratorOnly in aFlags) or not (self is TengShaderCodeGenerator)) and
  255. (not (sfParentsFileOnly in aFlags) or not (self is TengShaderFile))
  256. then
  257. result := result and Parent.FindIntern(aFlags, self, aResults);
  258. end;
  259. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean;
  261. var
  262. p: TengShaderPart;
  263. begin
  264. result := (aIncludeSelf and (self is aType)) or GetParent(aType, p);
  265. end;
  266. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  267. function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean;
  268. begin
  269. result := true;
  270. if (fParent is aType) then
  271. TengShaderPart(aPart) := fParent
  272. else if Assigned(fParent) then
  273. result := fParent.GetParent(aType, aPart)
  274. else
  275. result := false;
  276. end;
  277. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  278. function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
  279. begin
  280. if not GetParent(aType, result) then
  281. raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self);
  282. end;
  283. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  284. procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TSearchResults);
  285. begin
  286. FindIntern(aFlags, nil, aResults);
  287. end;
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. function TengShaderPart.GetEnumerator: TEnumerator;
  290. begin
  291. result := TEnumerator.Create(self);
  292. end;
  293. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  294. function TengShaderPart.GetReverseEnumerator: TEnumerator;
  295. begin
  296. result := TEnumerator.Create(self, true);
  297. end;
  298. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  299. constructor TengShaderPart.Create(const aParent: TengShaderPart);
  300. begin
  301. inherited Create;
  302. fParent := aParent;
  303. if Assigned(fParent)
  304. then fRoot := fParent.Root
  305. else fRoot := nil;
  306. end;
  307. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  308. class function TengShaderPart.GetTokenName: String;
  309. begin
  310. result := ''; // DUMMY
  311. end;
  312. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  313. class function TengShaderPart.CheckToken(const aToken: String): Boolean;
  314. begin
  315. result := (aToken = GetTokenName);
  316. end;
  317. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  318. class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  319. begin
  320. // DUMMY
  321. end;
  322. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  323. //TengShaderCodePart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  324. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. function TengShaderCodePart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  326. begin
  327. result := ''; // DUMMY
  328. end;
  329. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  330. function TengShaderCodePart.ParseText(const aArgs: TengParseArgs): String;
  331. var
  332. params: TengTokenParameterList;
  333. begin
  334. params := TengTokenParameterList.Create(Filename);
  335. try
  336. fCol := aArgs.Col;
  337. fLine := aArgs.Line;
  338. if (GetTokenName <> '') then
  339. aArgs.ExtractToken(self, params);
  340. result := ParseIntern(aArgs, params);
  341. finally
  342. FreeAndNil(params);
  343. end;
  344. end;
  345. end.