Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

634 řádky
25 KiB

  1. unit uengShaderFileExpression;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils, variants,
  7. uengShaderFileParser;
  8. type
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TengExpressionItem = class(TObject)
  11. private
  12. fOwner: TObject;
  13. fLine: Integer;
  14. fCol: Integer;
  15. fFilename: String;
  16. public
  17. property Owner: TObject read fOwner;
  18. property Line: Integer read fLine;
  19. property Col: Integer read fCol;
  20. property Filename: String read fFilename;
  21. function GetText: String; virtual;
  22. function GetValue: Variant; virtual;
  23. constructor Create(const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  24. end;
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  26. TengExpressionValue = class(TengExpressionItem)
  27. private
  28. fValue: Variant;
  29. public
  30. function GetText: String; override;
  31. function GetValue: Variant; override;
  32. constructor Create(const aValue: Variant; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  33. end;
  34. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  35. TengExpressionVariable = class(TengExpressionItem)
  36. private
  37. fName: String;
  38. public
  39. function GetText: String; override;
  40. function GetValue: Variant; override;
  41. constructor Create(const aName: String; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  42. end;
  43. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  44. TengExpressionGroup = class(TengExpressionItem)
  45. private
  46. fChild: TengExpressionItem;
  47. public
  48. property Child: TengExpressionItem read fChild write fChild;
  49. function GetText: String; override;
  50. function GetValue: Variant; override;
  51. constructor Create(const aChild: TengExpressionItem; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  52. destructor Destroy; override;
  53. end;
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  55. TengExpressionUnaryOperator = (
  56. opBinaryNot,
  57. opLogicalNot,
  58. opDefined,
  59. opSet
  60. );
  61. TengExpressionUnaryOperation = class(TengExpressionItem)
  62. private
  63. fChild: TengExpressionItem;
  64. fUnaryOp: TengExpressionUnaryOperator;
  65. public
  66. property Child: TengExpressionItem read fChild write fChild;
  67. property UnaryOp: TengExpressionUnaryOperator read fUnaryOp;
  68. function GetText: String; override;
  69. function GetValue: Variant; override;
  70. constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  71. destructor Destroy; override;
  72. end;
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. TengExpressionBinaryOperator = ( //order of elements in this enum is also the weight of the operators
  75. opBinaryOr, opBinaryAnd, opBinaryXor, // binary
  76. opMultiply, opDivide, opAdd, opSubtract, // arithmetic
  77. opLogicalOr, opLogicalAnd, opLogicalXor, // logical
  78. opEquals, opLesser, opGreater, opLEquals, opGEquals, opUnequals // comparison
  79. );
  80. TengExpressionBinaryOperation = class(TengExpressionItem)
  81. private
  82. fFirst: TengExpressionItem;
  83. fSecond: TengExpressionItem;
  84. fBinaryOp: TengExpressionBinaryOperator;
  85. public
  86. property First: TengExpressionItem read fFirst write fFirst;
  87. property Second: TengExpressionItem read fSecond write fSecond;
  88. property BinaryOp: TengExpressionBinaryOperator read fBinaryOp;
  89. function GetText: String; override;
  90. function GetValue: Variant; override;
  91. constructor Create(const aOperator: TengExpressionBinaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  92. destructor Destroy; override;
  93. end;
  94. function ParseExpression(const aOwner: TObject; const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  95. implementation
  96. uses
  97. uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper
  98. {$IFDEF USE_BITSPACE_UTILS}
  99. , uutlGenerics
  100. {$ELSE}
  101. , fgl
  102. {$ENDIF}
  103. ;
  104. const
  105. EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = (
  106. TOKEN_OP_BINARY_NOT, //opBinaryNot
  107. TOKEN_OP_LOGICAL_NOT, //opLogicalNot
  108. TOKEN_OP_DEFINED, //opDefined
  109. TOKEN_OP_SET //opSet
  110. );
  111. EXPRESSION_BINARY_OPERATIONS: array[TengExpressionBinaryOperator] of String = (
  112. TOKEN_OP_BINARY_OR, //opBinaryOr
  113. TOKEN_OP_BINARY_AND, //opBinaryAnd
  114. TOKEN_OP_BINARY_XOR, //opBinaryXor
  115. TOKEN_OP_MULTIPLY, //opMultiply
  116. TOKEN_OP_DIVIDE, //opDivide
  117. TOKEN_OP_ADD, //opAdd
  118. TOKEN_OP_SUBTRACT, //opSubtract
  119. TOKEN_OP_LOGICAL_OR, //opLogicalOr
  120. TOKEN_OP_LOGICAL_AND, //opLogicalAnd
  121. TOKEN_OP_LOGICAL_XOR, //opLogicalXor
  122. TOKEN_OP_EQUALS, //opEquals
  123. TOKEN_OP_LESSER, //opLesser
  124. TOKEN_OP_GREATER, //opGreater
  125. TOKEN_OP_LEQUALS, //opLEquals
  126. TOKEN_OP_GEQUALS, //opGEquals
  127. TOKEN_OP_UNEQUALS //opUnequals,
  128. );
  129. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. //TengExpressionItem////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. function TengExpressionItem.GetText: String;
  133. begin
  134. result := ''; // DUMMY
  135. end;
  136. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  137. function TengExpressionItem.GetValue: Variant;
  138. begin
  139. result := Unassigned; // DUMMY
  140. end;
  141. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. constructor TengExpressionItem.Create(const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  143. begin
  144. inherited Create;
  145. fOwner := aOwner;
  146. fLine := aLine;
  147. fCol := aCol;
  148. fFilename := aFilename;
  149. end;
  150. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. //TengExpressionValue///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. function TengExpressionValue.GetText: String;
  154. begin
  155. result := TOKEN_CHAR_QUOTE + fValue + TOKEN_CHAR_QUOTE;
  156. end;
  157. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  158. function TengExpressionValue.GetValue: Variant;
  159. begin
  160. result := fValue;
  161. end;
  162. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  163. constructor TengExpressionValue.Create(const aValue: Variant; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  164. begin
  165. inherited Create(aOwner, aLine, aCol, aFilename);
  166. fValue := aValue;
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. //TengExpressionVariable////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. function TengExpressionVariable.GetText: String;
  172. begin
  173. result := fName;
  174. end;
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. function TengExpressionVariable.GetValue: Variant;
  177. begin
  178. result := Unassigned; // TODO
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. constructor TengExpressionVariable.Create(const aName: String; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  182. begin
  183. inherited Create(aOwner, aLine, aCol, aFilename);
  184. fName := aName;
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. ///TengExpressionGroup//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. function TengExpressionGroup.GetText: String;
  190. begin
  191. if Assigned(fChild)
  192. then result := TOKEN_OP_GROUP_BEGIN + fChild.GetText + TOKEN_OP_GROUP_END
  193. else result := '';
  194. end;
  195. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  196. function TengExpressionGroup.GetValue: Variant;
  197. begin
  198. if Assigned(fChild)
  199. then result := fChild.GetValue
  200. else result := Unassigned;
  201. end;
  202. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  204. begin
  205. inherited Create(aOwner, aLine, aCol, aFilename);
  206. fChild := aChild;
  207. end;
  208. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  209. destructor TengExpressionGroup.Destroy;
  210. begin
  211. FreeAndNil(fChild);
  212. inherited Destroy;
  213. end;
  214. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  215. //TengExpressionUnaryOperation//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. function TengExpressionUnaryOperation.GetText: String;
  218. begin
  219. if not Assigned(fChild) then
  220. EengExpression.Create('no child assigned', self);
  221. result :=
  222. {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF}
  223. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText
  224. {$IFDEF EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF};
  225. end;
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. function TengExpressionUnaryOperation.GetValue: Variant;
  228. var
  229. v: Variant;
  230. begin
  231. if not Assigned(fChild) then
  232. raise EengExpression.Create('no child assigned', self);
  233. try
  234. case fUnaryOp of
  235. opBinaryNot: begin
  236. v := fChild.GetValue;
  237. result := not Integer(v);
  238. end;
  239. opLogicalNot: begin
  240. v := fChild.GetValue;
  241. result := not Boolean(v);
  242. end;
  243. opDefined: begin
  244. // TODO
  245. end;
  246. opSet: begin
  247. // TODO
  248. end;
  249. else
  250. result := inherited GetValue;
  251. end;
  252. except
  253. on ex: Exception do
  254. raise EengInvalidParamter.Create(
  255. ex.Message + '("' + GetText + '" ==> ' +
  256. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")',
  257. Line, Col, Filename, Owner);
  258. end;
  259. end;
  260. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  261. constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  262. begin
  263. inherited Create(aOwner, aLine, aCol, aFilename);
  264. fChild := nil;
  265. fUnaryOp := aUnaryOp;
  266. end;
  267. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  268. destructor TengExpressionUnaryOperation.Destroy;
  269. begin
  270. FreeAndNil(fChild);
  271. inherited Destroy;
  272. end;
  273. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  274. //TengExpressionBinaryOperation/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  276. function TengExpressionBinaryOperation.GetText: String;
  277. begin
  278. if not Assigned(fFirst) or not Assigned(fSecond) then
  279. raise EengExpression.Create('first or second item not assigned');
  280. result :=
  281. {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF}
  282. fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText
  283. {$IFDEF EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF};
  284. end;
  285. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  286. function TengExpressionBinaryOperation.GetValue: Variant;
  287. var
  288. v1: Variant;
  289. v2: Variant;
  290. begin
  291. if not Assigned(fFirst) or not Assigned(fSecond) then
  292. raise EengExpression.Create('first or second item not assigned');
  293. v1 := fFirst.GetValue;
  294. v2 := fSecond.GetValue;
  295. try
  296. case fBinaryOp of
  297. opBinaryOr: result := (Integer(v1) or Integer(v2));
  298. opBinaryAnd: result := (Integer(v1) and Integer(v2));
  299. opBinaryXor: result := (Integer(v1) xor Integer(v2));
  300. opMultiply: result := (v1 * v2);
  301. opDivide: result := (v1 / v2);
  302. opAdd: result := (v1 + v2);
  303. opSubtract: result := (v1 - v2);
  304. opLogicalOr: result := (Boolean(v1) or Boolean(v2));
  305. opLogicalAnd: result := (Boolean(v1) and Boolean(v2));
  306. opLogicalXor: result := (Boolean(v1) xor Boolean(v2));
  307. opEquals: result := (v1 = v2);
  308. opLesser: result := (v1 < v2);
  309. opGreater: result := (v1 > v2);
  310. opLEquals: result := (v1 <= v2);
  311. opGEquals: result := (v1 >= v2);
  312. opUnequals: result := (v1 <> v2);
  313. else
  314. result := inherited GetValue;
  315. end;
  316. except
  317. on ex: Exception do
  318. raise EengInvalidParamter.Create(
  319. ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' +
  320. EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")',
  321. fLine, fCol, fFilename, fOwner);
  322. end;
  323. end;
  324. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
  326. begin
  327. inherited Create(aOwner, aLine, aCol, aFilename);
  328. fBinaryOp := aOperator;
  329. fFirst := nil;
  330. fSecond := nil;
  331. end;
  332. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  333. destructor TengExpressionBinaryOperation.Destroy;
  334. begin
  335. FreeAndNil(fFirst);
  336. FreeAndNil(fSecond);
  337. inherited Destroy;
  338. end;
  339. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  340. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  341. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  342. type
  343. TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
  344. TExpectedParams = set of TExpectedParam;
  345. {$IFDEF USE_BITSPACE_UTILS}
  346. TExpressionItemStack = specialize TutlSimpleList<TengExpressionItem>;
  347. {$ELSE}
  348. TExpressionItemStack = class(specialize TFPList<TengExpressionItem>)
  349. public
  350. end;
  351. {$ENDIF}
  352. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  353. function ParseExpression(const aOwner: TObject; const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  354. var
  355. p: TengTokenParameter;
  356. procedure RaiseEx(const aMsg: String);
  357. begin
  358. raise EengExpression.Create(aMsg, p.Line, p.Col, aParam.Filename, aOwner);
  359. end;
  360. function NextParam: Boolean;
  361. begin
  362. inc(aIndex);
  363. result := (aIndex < aParam.Count);
  364. if result then
  365. p := aParam[aIndex];
  366. end;
  367. function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  368. begin
  369. result := true;
  370. for aOperator in TengExpressionUnaryOperator do
  371. if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
  372. exit;
  373. result := false;
  374. end;
  375. function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  376. begin
  377. result := true;
  378. for aOperator in TengExpressionBinaryOperator do
  379. if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
  380. exit;
  381. result := false;
  382. end;
  383. procedure MergeItems(const aStack: TExpressionItemStack; var aNew: TengExpressionItem);
  384. var
  385. item: TengExpressionItem;
  386. begin
  387. try
  388. if (aStack.Count = 0) then begin
  389. aStack.PushLast(aNew);
  390. aNew := nil;
  391. exit;
  392. end;
  393. item := aStack.Last;
  394. if (item is TengExpressionBinaryOperation) then begin
  395. if (aNew is TengExpressionBinaryOperation) then begin
  396. //both are binary operators, new is weaker then existing
  397. if ((aNew as TengExpressionBinaryOperation).BinaryOp <
  398. (item as TengExpressionBinaryOperation).BinaryOp) then
  399. begin
  400. (aNew as TengExpressionBinaryOperation).First := item;
  401. aStack.PopLast;
  402. aStack.PushLast(aNew);
  403. aNew := nil;
  404. //both are binary operators, new is stronger than existing
  405. end else begin
  406. if not Assigned((item as TengExpressionBinaryOperation).Second) then
  407. RaiseEx('inconsistent state');
  408. (aNew as TengExpressionBinaryOperation).First := (item as TengExpressionBinaryOperation).Second;
  409. (item as TengExpressionBinaryOperation).Second := aNew;
  410. aStack.PushLast(aNew);
  411. aNew := nil;
  412. end;
  413. //existing is binary operator, new is normal
  414. end else begin
  415. if Assigned((item as TengExpressionBinaryOperation).Second) then
  416. RaiseEx('inconsistent state');
  417. (item as TengExpressionBinaryOperation).Second := aNew;
  418. aNew := nil;
  419. while (aStack.Count > 1) do
  420. aStack.PopLast; //remove all but first
  421. end;
  422. end else begin
  423. //existing is normal item, new is binary operation
  424. if (aNew is TengExpressionBinaryOperation) then begin
  425. aStack.PopLast;
  426. (aNew as TengExpressionBinaryOperation).First := item;
  427. aStack.PushLast(aNew);
  428. aNew := nil;
  429. //existing is unary operation, new is normal item or unary operation
  430. end else if (item is TengExpressionUnaryOperation) then begin
  431. if Assigned((item as TengExpressionUnaryOperation).Child) then
  432. RaiseEx('inconsistent state');
  433. (item as TengExpressionUnaryOperation).Child := aNew;
  434. if not (aNew is TengExpressionUnaryOperation) then begin
  435. while (aStack.Count > 1) do
  436. aStack.PopLast; //remove all but first
  437. end else
  438. aStack.PushLast(aNew);
  439. aNew := nil;
  440. //existing and new are both normal items
  441. end else
  442. RaiseEx('inconsistent state');
  443. end;
  444. except
  445. FreeAndNil(aNew);
  446. raise;
  447. end;
  448. end;
  449. function BuildTree(const aDepth: Integer = 0): TengExpressionItem;
  450. var
  451. uOp: TengExpressionUnaryOperator;
  452. bOp: TengExpressionBinaryOperator;
  453. expected: TExpectedParams;
  454. stack: TExpressionItemStack;
  455. l, c: Integer;
  456. ei, tmp: TengExpressionItem;
  457. begin
  458. expected := [exVariable, exValue, exGroupBegin, exUnaryOperation];
  459. result := nil;
  460. stack := TExpressionItemStack.Create(false);
  461. try try
  462. repeat
  463. // GroupBegin
  464. if (p.Name = TOKEN_OP_GROUP_BEGIN) then begin
  465. if not (exGroupBegin in expected) then
  466. RaiseEx('unexpected ''' + p.Name + '''');
  467. l := p.Line;
  468. c := p.Col;
  469. if not NextParam then
  470. RaiseEx('unexpected end');
  471. tmp := BuildTree(aDepth + 1);
  472. ei := TengExpressionGroup.Create(tmp, aOwner, l, c, aParam.Filename);
  473. try
  474. MergeItems(stack, ei);
  475. if (p.Name <> TOKEN_OP_GROUP_END) then
  476. RaiseEx('missing ''' + TOKEN_OP_GROUP_END + '''');
  477. expected := [exBinaryOperation, exGroupEnd];
  478. except
  479. FreeAndNil(ei);
  480. raise;
  481. end;
  482. // GroupEnd
  483. end else if (p.Name = TOKEN_OP_GROUP_END) then begin
  484. if not (exGroupEnd in expected) or (aDepth = 0) then
  485. RaiseEx('unexpected ''' + TOKEN_OP_GROUP_END + '''');
  486. exit;
  487. // UnaryOperation
  488. end else if IsUnaryOperation(p.Name, uOp) then begin
  489. if not (exUnaryOperation in expected) then
  490. RaiseEx('unexpected operator: ' + p.Name);
  491. ei := TengExpressionUnaryOperation.Create(uOp, aOwner, p.Line, p.Col, aParam.Filename);
  492. try
  493. MergeItems(stack, ei);
  494. expected := [exVariable];
  495. if (uOp <> opDefined) then
  496. expected := expected + [exValue, exGroupBegin, exUnaryOperation]
  497. except
  498. FreeAndNil(ei);
  499. raise;
  500. end;
  501. // BinaryOperation
  502. end else if IsBinaryOperation(p.Name, bOp) then begin
  503. if not (exBinaryOperation in expected) then
  504. RaiseEx('unexpected operator: ' + p.Name);
  505. ei := TengExpressionBinaryOperation.Create(bOp, aOwner, p.Line, p.Col, aParam.Filename);
  506. try
  507. MergeItems(stack, ei);
  508. expected := [exVariable, exValue, exGroupBegin, exUnaryOperation];
  509. except
  510. FreeAndNil(ei);
  511. raise;
  512. end;
  513. // Value
  514. end else if p.Quoted and IsValidIdentifier(p.Name) then begin
  515. if not (exValue in expected) then
  516. RaiseEx('unexpected value: ' + p.Name);
  517. ei := TengExpressionValue.Create(p.Name, aOwner,p.Line, p.Col, aParam.Filename);
  518. try
  519. MergeItems(stack, ei);
  520. expected := [exGroupEnd, exBinaryOperation];
  521. except
  522. FreeAndNil(ei);
  523. raise;
  524. end;
  525. // Variable
  526. end else if IsValidIdentifier(p.Name) then begin
  527. if not (exVariable in expected) then
  528. RaiseEx('unexpected variable: ' + p.Name);
  529. ei := TengExpressionVariable.Create(p.Name, aOwner, p.Line, p.Col, aParam.Filename);
  530. try
  531. MergeItems(stack, ei);
  532. expected := [exGroupEnd, exBinaryOperation];
  533. except
  534. FreeAndNil(ei);
  535. raise
  536. end;
  537. // Unknown
  538. end else
  539. RaiseEx('invalid parameter: ' + p.Name);
  540. until not NextParam;
  541. except
  542. if (stack.Count > 0) then begin
  543. stack[0].Free;
  544. stack[0] := nil;
  545. end;
  546. raise;
  547. end;
  548. finally
  549. if (stack.Count > 0) then
  550. result := stack[0];
  551. FreeAndNil(stack);
  552. end;
  553. end;
  554. begin
  555. dec(aIndex);
  556. if not NextParam then with aParam[0] do
  557. raise EengShaderPartInternal.Create('invalid parameter count in expression', Line, Col, aParam.Filename, aOwner);
  558. result := BuildTree;
  559. end;
  560. end.