25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
8.5 KiB

  1. unit uengShaderPartIf;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderPart, uengShaderPartScope, uengShaderFileExpression, uengShaderFileParser;
  8. type
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TengShaderPartIf = class(TengShaderCodePart)
  11. { Code Loading & Storage }
  12. private
  13. fExpression: TengExpressionItem;
  14. fIfPart: TengShaderCodePart;
  15. fElsePart: TengShaderCodePart;
  16. function HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
  17. protected
  18. function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; virtual;
  19. function GetCount: Integer; override;
  20. function GetChild(const aIndex: Integer): TengShaderPart; override;
  21. function GetText: String; override;
  22. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  23. { General }
  24. protected
  25. function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; override;
  26. public
  27. property Expression: TengExpressionItem read fExpression;
  28. destructor Destroy; override;
  29. { Class Methods }
  30. public
  31. class function GetTokenName: String; override;
  32. end;
  33. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  34. TengShaderPartElIf = class(TengShaderPartIf)
  35. { Code Loading & Storage }
  36. protected
  37. function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; override;
  38. { Class Methods }
  39. public
  40. class function GetTokenName: String; override;
  41. end;
  42. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. TengShaderPartElse = class(TengShaderPartScope)
  44. { Code Loading & Storage }
  45. protected
  46. function GetText: String; override;
  47. { Class Methods }
  48. public
  49. class function GetTokenName: String; override;
  50. end;
  51. implementation
  52. uses
  53. uengShaderFileTypes, uengShaderFileConstants, uengShaderFileHelper;
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  55. //TengShaderPartIf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. function TengShaderPartIf.HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
  58. const
  59. TOKEN_CLASSES: array[0..1] of CengShaderCodePart = (
  60. TengShaderPartElse,
  61. TengShaderPartElIf
  62. );
  63. var
  64. c: CengShaderCodePart;
  65. begin
  66. for c in TOKEN_CLASSES do begin
  67. if c.CheckToken(aToken) then begin
  68. c.Validate(aArgs, self);
  69. fElsePart := c.Create(self);
  70. break;
  71. end;
  72. end;
  73. if Assigned(fElsePart) then
  74. result := fElsePart.ParseText(aArgs);
  75. result := HandeEndToken(result, aArgs);
  76. end;
  77. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  78. function TengShaderPartIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String;
  79. begin
  80. result := CheckEndToken(aArgs, self);
  81. end;
  82. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  83. function TengShaderPartIf.GetCount: Integer;
  84. begin
  85. result := 1;
  86. if Assigned(fElsePart) then
  87. inc(result, 1);
  88. end;
  89. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. function TengShaderPartIf.GetChild(const aIndex: Integer): TengShaderPart;
  91. begin
  92. if (aIndex < 0) or (aIndex >= Count) then
  93. raise EengOutOfRange.Create(0, Count-1, aIndex, self);
  94. case aIndex of
  95. 0: result := fIfPart;
  96. 1: result := fElsePart;
  97. end;
  98. end;
  99. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  100. function TengShaderPartIf.GetText: String;
  101. begin
  102. result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fExpression.Text + TOKEN_CHAR_END + fIfPart.Text;
  103. if Assigned(fElsePart) then
  104. result := result + fElsePart.Text;
  105. result := result + TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END;
  106. end;
  107. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. function TengShaderPartIf.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  109. begin
  110. if (aParams[0].Name <> GetTokenName) then with aParams[0] do
  111. raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
  112. if (aParams.Count < 2) then
  113. raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);
  114. fExpression := ParseExpression(self, aParams, 1);
  115. fIfPart := TengShaderPartScope.Create(self);
  116. result := fIfPart.ParseText(aArgs);
  117. result := HandleToken(result, aArgs);
  118. end;
  119. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  120. function TengShaderPartIf.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean;
  121. begin
  122. result := true;
  123. if (sfEvaluateIf in aFlags) and (sfSearchChildren in aFlags) then begin
  124. if fExpression.GetValue then begin
  125. if Assigned(fIfPart) then
  126. fIfPart.Find(aFlags, aResults);
  127. end else begin
  128. if Assigned(fElsePart) then
  129. fElsePart.Find(aFlags, aResults);
  130. end;
  131. end;
  132. if not (sfSearchAllIf in aFlags) and (sfSearchChildren in aFlags) then
  133. aFlags := aFlags - [sfSearchChildren] + [sfSearchChildrenLazy];
  134. result := result and inherited FindIntern(aFlags, aChild, aResults);
  135. end;
  136. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  137. destructor TengShaderPartIf.Destroy;
  138. begin
  139. FreeAndNil(fExpression);
  140. FreeAndNil(fIfPart);
  141. FreeAndNil(fElsePart);
  142. inherited Destroy;
  143. end;
  144. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. class function TengShaderPartIf.GetTokenName: String;
  146. begin
  147. result := TOKEN_IF;
  148. end;
  149. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  150. //TengShaderPartElIf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. function TengShaderPartElIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String;
  153. begin
  154. result := aToken;
  155. if (result <> TOKEN_END) then
  156. raise EengInvalidToken.Create(ClassName, result, aArgs.Line, aArgs.Col, Filename, self);
  157. end;
  158. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. class function TengShaderPartElIf.GetTokenName: String;
  160. begin
  161. result := TOKEN_ELIF;
  162. end;
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. //TengShaderPartElse////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  166. function TengShaderPartElse.GetText: String;
  167. begin
  168. result := TOKEN_CHAR_BEGIN + GetTokenName + TOKEN_CHAR_END + inherited GetText;
  169. end;
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. class function TengShaderPartElse.GetTokenName: String;
  172. begin
  173. result := TOKEN_ELSE;
  174. end;
  175. end.