Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

332 wiersze
12 KiB

  1. unit uengShaderFileHelper;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. uengShaderPart, uengShaderFileParser;
  7. type
  8. TInfoFlag = (
  9. ifWarning,
  10. ifRaiseEx
  11. );
  12. TInfoFlags = set of TInfoFlag;
  13. function IsValidIdentifier(const aIdent: String): Boolean;
  14. function CheckEndToken(const aToken: String; const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String;
  15. function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
  16. function ExtractSearchResult(
  17. const aSender: TengShaderPart;
  18. const aIdent: String;
  19. const aList: TengShaderPartList;
  20. const aFlags: TInfoFlags = [ifWarning, ifRaiseEx];
  21. aLine: Integer = -1;
  22. aCol: Integer = -1;
  23. aFilename: String = ''): TengShaderPart;
  24. type
  25. TengSearchFlag = (
  26. sfSearchChildren, // search in children
  27. sfEvaluateIf, // evaluate if and search in suitable subtree
  28. sfIgnoreIf, // do not search in if items
  29. sfSearchChildrenLazy, // set sfSearchChildren in next recursion level
  30. sfSearchParents, // search in Parents
  31. sfSearchInherited, // search in inherited classes
  32. sfIgnoreOwner // ignore owner of search walker
  33. );
  34. TengSearchFlags = set of TengSearchFlag;
  35. TengSearchResults = class(TengShaderPartList)
  36. public
  37. constructor Create;
  38. end;
  39. TengSearchWalker = class(TengShaderPartWalker)
  40. private type
  41. TArgs = packed record
  42. Flags: TengSearchFlags;
  43. end;
  44. PArgs = ^TArgs;
  45. private
  46. fOwner: TengShaderPart;
  47. fResults: TengSearchResults;
  48. fSearchFlags: TengSearchFlags;
  49. fResultTypes: CengShaderPartArr;
  50. fChildrenDoNotLeave: CengShaderPartArr;
  51. fParentsDoNotLeave: CengShaderPartArr;
  52. fChildrenForceLeave: CengShaderPartArr;
  53. fParentsForceLeave: CengShaderPartArr;
  54. protected
  55. procedure Visit(const aPart, aSender: TengShaderPart; const aArgs: Pointer); override;
  56. function Check(const aPart: TengShaderPart): Boolean; virtual;
  57. public
  58. property Owner: TengShaderPart read fOwner write fOwner;
  59. property SearchFlags: TengSearchFlags read fSearchFlags write fSearchFlags;
  60. property ResultTypes: CengShaderPartArr read fResultTypes write fResultTypes;
  61. property ChildrenDoNotLeave: CengShaderPartArr read fChildrenDoNotLeave write fChildrenDoNotLeave;
  62. property ParentsDoNotLeave: CengShaderPartArr read fParentsDoNotLeave write fParentsDoNotLeave;
  63. property ChildrenForceLeave: CengShaderPartArr read fChildrenForceLeave write fChildrenForceLeave;
  64. property ParentsForceLeave: CengShaderPartArr read fParentsForceLeave write fParentsForceLeave;
  65. constructor Create(const aResults: TengSearchResults);
  66. end;
  67. TengKeyValuePairSearchWalker = class(TengSearchWalker)
  68. private
  69. fName: String;
  70. protected
  71. function Check(const aPart: TengShaderPart): Boolean; override;
  72. public
  73. property Name: String read fName write fName;
  74. end;
  75. TengProcSearchWalker = class(TengSearchWalker)
  76. private
  77. fName: String;
  78. protected
  79. function Check(const aPart: TengShaderPart): Boolean; override;
  80. public
  81. property Name: String read fName write fName;
  82. constructor Create(const aResults: TengSearchResults);
  83. end;
  84. implementation
  85. uses
  86. sysutils,
  87. uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc,
  88. uengShaderPartIf, uengShaderPartClass;
  89. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. function IsValidIdentifier(const aIdent: String): Boolean;
  91. var
  92. i, len: Integer;
  93. begin
  94. len := Length(aIdent);
  95. result := false;
  96. for i := 1 to len do
  97. if not (aIdent[i] in VALID_IDENT_CHARS) then
  98. exit;
  99. result := true;
  100. end;
  101. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. function CheckEndToken(const aToken: String; const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String;
  103. var
  104. oldLine, oldCol: Integer;
  105. param: TengTokenParameterList;
  106. begin
  107. oldLine := aArgs.Line;
  108. oldCol := aArgs.Col;
  109. if (aToken <> TOKEN_END) then
  110. raise EengUnexpectedToken.Create(aToken, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
  111. param := TengTokenParameterList.Create('');
  112. try
  113. if not aArgs.ExtractToken(aShaderPart, param) then
  114. EengUnexpectedToken.Create(TOKEN_NONE, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
  115. if (param[0].Name <> TOKEN_END) then
  116. EengUnexpectedToken.Create(param[0].Name, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
  117. if (param.Count <> 1) then
  118. EengInvalidParamterCount.Create(TOKEN_END, 1, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
  119. result := '';
  120. finally
  121. FreeAndNil(param);
  122. end;
  123. end;
  124. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  125. function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
  126. var
  127. t: CengShaderPart;
  128. begin
  129. result := true;
  130. for t in aTypes do
  131. if (aShaderPart is t) then
  132. exit;
  133. result := (Length(aTypes) = 0);
  134. end;
  135. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  136. function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList;
  137. const aFlags: TInfoFlags; aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart;
  138. var
  139. s: String;
  140. i: Integer;
  141. begin
  142. result := nil;
  143. if Assigned(aSender) then begin
  144. if (aLine < 0) then
  145. aLine := aSender.Line;
  146. if (aCol < 0) then
  147. aCol := aSender.Col;
  148. if (aFilename = '') then
  149. aFilename := aSender.Filename;
  150. end;
  151. if (aList.Count <= 0) then begin
  152. if (ifRaiseEx in aFlags) then
  153. raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender);
  154. exit;
  155. end;
  156. result := aList[aList.Count-1];
  157. if (aList.Count > 1) and Assigned(aSender) and (ifWarning in aFlags) then begin
  158. s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, result.Filename, result.Line + 1, result.Col]) + sLineBreak +
  159. 'previously declared here:' + sLineBreak;
  160. i := aList.Count - 2;
  161. while (i >= 0) do begin
  162. s := s + Format(' %s %d:%d', [aList[i].Filename, aList[i].Line + 1, aList[i].Col]) + sLineBreak;
  163. dec(i);
  164. end;
  165. aSender.LogMsg(llWarning, s);
  166. end;
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. //TengSearchResults/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. constructor TengSearchResults.Create;
  172. begin
  173. inherited Create(false);
  174. end;
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. //TengSearchWalker//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  177. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  178. procedure TengSearchWalker.Visit(const aPart, aSender: TengShaderPart; const aArgs: Pointer);
  179. var
  180. args: TArgs;
  181. function VisitChild(const aItem: TengShaderPart): Boolean;
  182. var
  183. c: CengShaderPart;
  184. begin
  185. result := (sfSearchChildren in args.Flags) and Assigned(aItem) and (aItem <> aSender);
  186. if not result then
  187. exit;
  188. for c in fChildrenDoNotLeave do
  189. if (aItem is c) then
  190. result := false;
  191. for c in fChildrenForceLeave do
  192. if (aItem is c) then
  193. result := true;
  194. end;
  195. function VisitParent: Boolean;
  196. var
  197. c: CengShaderPart;
  198. begin
  199. result := (sfSearchParents in args.Flags) and Assigned(aPart.Parent) and (aPart.Parent <> aSender);
  200. if not result then
  201. exit;
  202. for c in fParentsDoNotLeave do
  203. if (aPart is c) then
  204. result := false;
  205. for c in fParentsForceLeave do
  206. if (aPart is c) then
  207. result := true;
  208. end;
  209. var
  210. p: TengShaderPart;
  211. c: TengShaderPartClass;
  212. nextArgs: TArgs;
  213. begin
  214. if not Assigned(aPart) then
  215. exit;
  216. if Assigned(aArgs) then
  217. args := PArgs(aArgs)^
  218. else
  219. args.Flags := fSearchFlags;
  220. // visit parent
  221. nextArgs := args;
  222. if (sfSearchChildrenLazy in nextArgs.Flags) then
  223. nextArgs.Flags := nextArgs.Flags + [sfSearchChildren] - [sfSearchChildrenLazy];
  224. if Check(aPart.Parent) then
  225. fResults.Add(aPart.Parent);
  226. if VisitParent then
  227. Visit(aPart.Parent, aPart, @nextArgs);
  228. // visit inherited
  229. if (sfSearchInherited in args.Flags) and (aPart is TengShaderPartClass) then begin
  230. for c in (aPart as TengShaderPartClass).InheritedClasses do
  231. Visit(c, aPart, @nextArgs);
  232. end;
  233. // visit children
  234. if (sfSearchChildren in args.Flags) then begin
  235. if (aPart is TengShaderPartIf) then with (aPart as TengShaderPartIf) do begin
  236. if (sfEvaluateIf in args.Flags) then begin
  237. if Expression.GetValue
  238. then p := IfPart
  239. else p := ElsePart;
  240. if Assigned(p) then
  241. Visit(p, aPart, @nextArgs);
  242. exit;
  243. end else if (sfIgnoreIf in args.Flags) then
  244. exit;
  245. end;
  246. for p in aPart do begin
  247. if Check(p) then
  248. fResults.Add(p);
  249. if VisitChild(p) then
  250. Visit(p, aPart, @nextArgs);
  251. end;
  252. end;
  253. end;
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. function TengSearchWalker.Check(const aPart: TengShaderPart): Boolean;
  256. var
  257. c: CengShaderPart;
  258. begin
  259. result := (aPart <> fOwner) or not (sfIgnoreOwner in fSearchFlags);
  260. if result then
  261. for c in fResultTypes do
  262. if (aPart is c) then
  263. exit;
  264. result := false;
  265. end;
  266. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  267. constructor TengSearchWalker.Create(const aResults: TengSearchResults);
  268. begin
  269. inherited Create;
  270. fResults := aResults;
  271. end;
  272. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  273. //TengKeyValuePairSearchWalker//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  274. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275. function TengKeyValuePairSearchWalker.Check(const aPart: TengShaderPart): Boolean;
  276. begin
  277. result :=
  278. inherited Check(aPart) and
  279. (aPart is TengShaderPartKeyValuePair) and
  280. ((aPart as TengShaderPartKeyValuePair).Name = fName);
  281. end;
  282. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  283. //TengProcSearchWalker//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  284. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  285. function TengProcSearchWalker.Check(const aPart: TengShaderPart): Boolean;
  286. begin
  287. result :=
  288. inherited Check(aPart) and
  289. (aPart is TengShaderPartProc) and
  290. ((aPart as TengShaderPartProc).Name = fName);
  291. end;
  292. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  293. constructor TengProcSearchWalker.Create(const aResults: TengSearchResults);
  294. begin
  295. inherited Create(aResults);
  296. ResultTypes := CengShaderPartArr.Create(TengShaderPartProc);
  297. end;
  298. end.