You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

769 lines
32 KiB

  1. unit uengShaderFileExpression;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils, variants,
  7. uengShaderPart, uengShaderFileParser, uengShaderPartKeyValuePair;
  8. type
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TengExpressionItem = class(TengShaderPart)
  11. public
  12. function GetValue: Variant; virtual;
  13. constructor Create(const aLine, aCol: Integer); reintroduce;
  14. end;
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. TengExpressionValue = class(TengExpressionItem)
  17. private
  18. fValue: Variant;
  19. public
  20. property Value: Variant read fValue;
  21. function GetText: String; override;
  22. function GetValue: Variant; override;
  23. constructor Create(const aValue: Variant; const aLine, aCol: Integer);
  24. end;
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  26. TengExpressionVariable = class(TengExpressionItem)
  27. private
  28. fName: String;
  29. fPart: TengShaderPartKeyValuePair;
  30. public
  31. property Name: String read fName;
  32. property Part: TengShaderPartKeyValuePair read fPart;
  33. function GetText: String; override;
  34. function GetValue: Variant; override;
  35. constructor Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
  36. end;
  37. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  38. TengExpressionGroup = class(TengExpressionItem)
  39. private
  40. fChild: TengExpressionItem;
  41. protected
  42. function GetCount: Integer; override;
  43. function GetChild(const aIndex: Integer): TengShaderPart; override;
  44. public
  45. property Child: TengExpressionItem read fChild;
  46. function GetText: String; override;
  47. function GetValue: Variant; override;
  48. constructor Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
  49. destructor Destroy; override;
  50. end;
  51. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. TengExpressionOperation = class(TengExpressionItem)
  53. protected
  54. function GetWeight: Integer; virtual;
  55. public
  56. property Weight: Integer read GetWeight;
  57. function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; virtual;
  58. function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; virtual;
  59. end;
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. TengExpressionUnaryOperator = (
  62. opBinaryNot,
  63. opLogicalNot
  64. );
  65. TengExpressionUnaryOperation = class(TengExpressionOperation)
  66. private
  67. fChild: TengExpressionItem;
  68. fUnaryOp: TengExpressionUnaryOperator;
  69. protected
  70. function GetWeight: Integer; override;
  71. function GetCount: Integer; override;
  72. function GetChild(const aIndex: Integer): TengShaderPart; override;
  73. public
  74. property Child: TengExpressionItem read fChild;
  75. property UnaryOp: TengExpressionUnaryOperator read fUnaryOp;
  76. function GetText: String; override;
  77. function GetValue: Variant; override;
  78. function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
  79. function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;
  80. constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
  81. destructor Destroy; override;
  82. end;
  83. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  84. TengExpressionBinaryOperator = ( //order of elements in this enum is also the weight of the operators
  85. opBinaryOr, opBinaryAnd, opBinaryXor, // binary
  86. opMultiply, opDivide, opAdd, opSubtract, // arithmetic
  87. opLogicalOr, opLogicalAnd, opLogicalXor, // logical
  88. opEquals, opLesser, opGreater, opLEquals, opGEquals, opUnequals // comparison
  89. );
  90. TengExpressionBinaryOperation = class(TengExpressionOperation)
  91. private
  92. fFirst: TengExpressionItem;
  93. fSecond: TengExpressionItem;
  94. fBinaryOp: TengExpressionBinaryOperator;
  95. protected
  96. function GetWeight: Integer; override;
  97. function GetCount: Integer; override;
  98. function GetChild(const aIndex: Integer): TengShaderPart; override;
  99. public
  100. property First: TengExpressionItem read fFirst write fFirst;
  101. property Second: TengExpressionItem read fSecond write fSecond;
  102. property BinaryOp: TengExpressionBinaryOperator read fBinaryOp;
  103. function GetText: String; override;
  104. function GetValue: Variant; override;
  105. function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
  106. function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;
  107. constructor Create(const aOperator: TengExpressionBinaryOperator; const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
  108. destructor Destroy; override;
  109. end;
  110. function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  111. implementation
  112. uses
  113. uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartScope, uengShaderFile;
  114. const
  115. EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = (
  116. TOKEN_OP_BINARY_NOT, //opBinaryNot
  117. TOKEN_OP_LOGICAL_NOT //opLogicalNot
  118. );
  119. EXPRESSION_BINARY_OPERATIONS: array[TengExpressionBinaryOperator] of String = (
  120. TOKEN_OP_BINARY_OR, //opBinaryOr
  121. TOKEN_OP_BINARY_AND, //opBinaryAnd
  122. TOKEN_OP_BINARY_XOR, //opBinaryXor
  123. TOKEN_OP_MULTIPLY, //opMultiply
  124. TOKEN_OP_DIVIDE, //opDivide
  125. TOKEN_OP_ADD, //opAdd
  126. TOKEN_OP_SUBTRACT, //opSubtract
  127. TOKEN_OP_LOGICAL_OR, //opLogicalOr
  128. TOKEN_OP_LOGICAL_AND, //opLogicalAnd
  129. TOKEN_OP_LOGICAL_XOR, //opLogicalXor
  130. TOKEN_OP_EQUALS, //opEquals
  131. TOKEN_OP_LESSER, //opLesser
  132. TOKEN_OP_GREATER, //opGreater
  133. TOKEN_OP_LEQUALS, //opLEquals
  134. TOKEN_OP_GEQUALS, //opGEquals
  135. TOKEN_OP_UNEQUALS //opUnequals
  136. );
  137. UNARY_OPERATION_WEIGHTS: array[TengExpressionUnaryOperator] of Integer = (
  138. 00, //opBinaryNot
  139. 00 //opLogicalNot
  140. );
  141. BINARY_OPERATION_WEIGHTS: array[TengExpressionBinaryOperator] of Integer = (
  142. 01, //opBinaryOr
  143. 02, //opBinaryAnd
  144. 03, //opBinaryXor
  145. 04, //opMultiply
  146. 05, //opDivide
  147. 06, //opAdd
  148. 07, //opSubtract
  149. 14, //opLogicalOr
  150. 15, //opLogicalAnd
  151. 16, //opLogicalXor
  152. 08, //opEquals
  153. 09, //opLesser
  154. 10, //opGreater
  155. 11, //opLEquals
  156. 12, //opGEquals
  157. 13 //opUnequals
  158. );
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. //TengExpressionItem////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  161. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. function TengExpressionItem.GetValue: Variant;
  163. begin
  164. result := Unassigned; // DUMMY
  165. end;
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. constructor TengExpressionItem.Create(const aLine, aCol: Integer);
  168. begin
  169. inherited Create(nil);
  170. fLine := aLine;
  171. fCol := aCol;
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. //TengExpressionValue///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. function TengExpressionValue.GetText: String;
  177. begin
  178. result := TOKEN_CHAR_QUOTE + fValue + TOKEN_CHAR_QUOTE;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. function TengExpressionValue.GetValue: Variant;
  182. begin
  183. result := fValue;
  184. end;
  185. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  186. constructor TengExpressionValue.Create(const aValue: Variant; const aLine, aCol: Integer);
  187. begin
  188. inherited Create(aLine, aCol);
  189. fValue := aValue;
  190. end;
  191. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  192. //TengExpressionVariable////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  193. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. function TengExpressionVariable.GetText: String;
  195. begin
  196. result := fName;
  197. end;
  198. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. function TengExpressionVariable.GetValue: Variant;
  200. begin
  201. result := Unassigned;
  202. if Assigned(fPart) then
  203. result := fPart.Value;
  204. end;
  205. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  206. constructor TengExpressionVariable.Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
  207. begin
  208. inherited Create(aLine, aCol);
  209. fName := aName;
  210. fPart := aPart;
  211. end;
  212. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213. //TengExpressionGroup///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  215. function TengExpressionGroup.GetCount: Integer;
  216. begin
  217. result := 1;
  218. end;
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. function TengExpressionGroup.GetChild(const aIndex: Integer): TengShaderPart;
  221. begin
  222. if (aIndex >= 0) and (aIndex < 1)
  223. then result := fChild
  224. else raise EengOutOfRange.Create(0, 0, aIndex, self);
  225. end;
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. function TengExpressionGroup.GetText: String;
  228. begin
  229. if Assigned(fChild)
  230. then result := TOKEN_OP_GROUP_BEGIN + fChild.GetText + TOKEN_OP_GROUP_END
  231. else result := '';
  232. end;
  233. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. function TengExpressionGroup.GetValue: Variant;
  235. begin
  236. if Assigned(fChild)
  237. then result := fChild.GetValue
  238. else result := Unassigned;
  239. end;
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
  242. begin
  243. inherited Create(aLine, aCol);
  244. fChild := aChild;
  245. end;
  246. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  247. destructor TengExpressionGroup.Destroy;
  248. begin
  249. FreeAndNil(fChild);
  250. inherited Destroy;
  251. end;
  252. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  253. //TengExpressionOperation///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. function TengExpressionOperation.GetWeight: Integer;
  256. begin
  257. result := -1;
  258. end;
  259. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. function TengExpressionOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  261. begin
  262. result := nil;
  263. end;
  264. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  265. function TengExpressionOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  266. begin
  267. result := nil;
  268. end;
  269. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  270. //TengExpressionUnaryOperation//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  271. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  272. function TengExpressionUnaryOperation.GetWeight: Integer;
  273. begin
  274. result := UNARY_OPERATION_WEIGHTS[fUnaryOp];
  275. end;
  276. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  277. function TengExpressionUnaryOperation.GetCount: Integer;
  278. begin
  279. result := 1;
  280. end;
  281. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  282. function TengExpressionUnaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
  283. begin
  284. if (aIndex >= 0) and (aIndex < 1)
  285. then result := fChild
  286. else raise EengOutOfRange.Create(0, 0, aIndex, self);
  287. end;
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. function TengExpressionUnaryOperation.GetText: String;
  290. begin
  291. if not Assigned(fChild) then
  292. EengExpression.Create('no child assigned', self);
  293. result :=
  294. {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF}
  295. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText
  296. {$IFDEF EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF};
  297. end;
  298. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  299. function TengExpressionUnaryOperation.GetValue: Variant;
  300. var
  301. v: Variant;
  302. begin
  303. if not Assigned(fChild) then
  304. raise EengExpression.Create('no child assigned', self);
  305. try
  306. case fUnaryOp of
  307. opBinaryNot: begin
  308. v := fChild.GetValue;
  309. result := not Integer(v);
  310. end;
  311. opLogicalNot: begin
  312. v := fChild.GetValue;
  313. result := not Boolean(v);
  314. end;
  315. else
  316. result := inherited GetValue;
  317. end;
  318. except
  319. on ex: Exception do
  320. raise EengInvalidParamter.Create(
  321. ex.Message + '("' + GetText + '" ==> ' +
  322. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")',
  323. Line, Col, Filename, self);
  324. end;
  325. end;
  326. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  327. function TengExpressionUnaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  328. begin
  329. result := fChild;
  330. fChild := aItem;
  331. end;
  332. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  333. function TengExpressionUnaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  334. begin
  335. result := fChild;
  336. fChild := aItem;
  337. end;
  338. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
  340. begin
  341. inherited Create(aLine, aCol);
  342. fChild := aChild;
  343. fUnaryOp := aUnaryOp;
  344. end;
  345. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  346. destructor TengExpressionUnaryOperation.Destroy;
  347. begin
  348. FreeAndNil(fChild);
  349. inherited Destroy;
  350. end;
  351. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  352. //TengExpressionBinaryOperation/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  353. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  354. function TengExpressionBinaryOperation.GetWeight: Integer;
  355. begin
  356. result := BINARY_OPERATION_WEIGHTS[fBinaryOp];
  357. end;
  358. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  359. function TengExpressionBinaryOperation.GetCount: Integer;
  360. begin
  361. result := 2;
  362. end;
  363. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  364. function TengExpressionBinaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
  365. begin
  366. if (aIndex < 0) and (aIndex >= 2) then
  367. raise EengOutOfRange.Create(0, 1, aIndex, self);
  368. case aIndex of
  369. 0: result := fFirst;
  370. 1: result := fSecond;
  371. end;
  372. end;
  373. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  374. function TengExpressionBinaryOperation.GetText: String;
  375. begin
  376. if not Assigned(fFirst) or not Assigned(fSecond) then
  377. raise EengExpression.Create('first or second item not assigned');
  378. result :=
  379. {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF}
  380. fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText
  381. {$IFDEF EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF};
  382. end;
  383. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  384. function TengExpressionBinaryOperation.GetValue: Variant;
  385. var
  386. v1: Variant;
  387. v2: Variant;
  388. begin
  389. if not Assigned(fFirst) or not Assigned(fSecond) then
  390. raise EengExpression.Create('first or second item not assigned');
  391. v1 := fFirst.GetValue;
  392. v2 := fSecond.GetValue;
  393. try
  394. case fBinaryOp of
  395. opBinaryOr: result := (Integer(v1) or Integer(v2));
  396. opBinaryAnd: result := (Integer(v1) and Integer(v2));
  397. opBinaryXor: result := (Integer(v1) xor Integer(v2));
  398. opMultiply: result := (v1 * v2);
  399. opDivide: result := (v1 / v2);
  400. opAdd: result := (v1 + v2);
  401. opSubtract: result := (v1 - v2);
  402. opLogicalOr: result := (Boolean(v1) or Boolean(v2));
  403. opLogicalAnd: result := (Boolean(v1) and Boolean(v2));
  404. opLogicalXor: result := (Boolean(v1) xor Boolean(v2));
  405. opEquals: result := (v1 = v2);
  406. opLesser: result := (v1 < v2);
  407. opGreater: result := (v1 > v2);
  408. opLEquals: result := (v1 <= v2);
  409. opGEquals: result := (v1 >= v2);
  410. opUnequals: result := (v1 <> v2);
  411. else
  412. result := inherited GetValue;
  413. end;
  414. except
  415. on ex: Exception do
  416. raise EengInvalidParamter.Create(
  417. ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' +
  418. EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")',
  419. self);
  420. end;
  421. end;
  422. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  423. function TengExpressionBinaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  424. begin
  425. result := fFirst;
  426. fFirst := aItem;
  427. end;
  428. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  429. function TengExpressionBinaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  430. begin
  431. result := fSecond;
  432. fSecond := aItem;
  433. end;
  434. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  435. constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator;
  436. const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
  437. begin
  438. inherited Create(aLine, aCol);
  439. fBinaryOp := aOperator;
  440. fFirst := aFirst;
  441. fSecond := aSecond;
  442. end;
  443. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  444. destructor TengExpressionBinaryOperation.Destroy;
  445. begin
  446. FreeAndNil(fFirst);
  447. FreeAndNil(fSecond);
  448. inherited Destroy;
  449. end;
  450. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  451. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  452. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  453. type
  454. TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
  455. TExpectedParams = set of TExpectedParam;
  456. TExpressionParser = class(TObject)
  457. private
  458. fParent: TengShaderPart;
  459. fParamPos: Integer;
  460. fParams: TengTokenParameterList;
  461. private
  462. function NextParam(out aParam: TengTokenParameter): Boolean;
  463. function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  464. function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  465. procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  466. function Move(var aItem: TengExpressionItem): TengExpressionItem;
  467. function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  468. function GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  469. public
  470. function GetGroup: TengExpressionItem;
  471. constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  472. end;
  473. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  474. //TExpressionParser/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  475. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  476. function TExpressionParser.NextParam(out aParam: TengTokenParameter): Boolean;
  477. begin
  478. inc(fParamPos);
  479. result := (fParamPos < fParams.Count);
  480. if result
  481. then aParam := fParams[fParamPos]
  482. else FillByte(aParam, SizeOf(aParam), 0);
  483. end;
  484. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  485. function TExpressionParser.IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  486. begin
  487. result := true;
  488. for aOperator in TengExpressionUnaryOperator do
  489. if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
  490. exit;
  491. result := false;
  492. end;
  493. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  494. function TExpressionParser.IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  495. begin
  496. result := true;
  497. for aOperator in TengExpressionBinaryOperator do
  498. if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
  499. exit;
  500. result := false;
  501. end;
  502. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  503. procedure TExpressionParser.RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  504. begin
  505. if (aName = '') then
  506. aName := aParam.Name;
  507. raise EengExpression.Create(aMsg + ' ' + aParam.Name, aParam.Line, aParam.Col, fParent.Filename, fParent);
  508. end;
  509. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  510. function TExpressionParser.Move(var aItem: TengExpressionItem): TengExpressionItem;
  511. begin
  512. result := aItem;
  513. aItem := nil;
  514. end;
  515. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  516. function TExpressionParser.Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  517. var
  518. o, n: TengExpressionOperation;
  519. tmp: TengExpressionItem;
  520. begin
  521. result := nil;
  522. try
  523. if not Assigned(aOld) then begin
  524. result := aNew;
  525. exit;
  526. end else if not Assigned(aNew) then begin
  527. result := aOld;
  528. exit;
  529. end else if (aOld is TengExpressionOperation) and (aNew is TengExpressionOperation) then begin
  530. o := (aOld as TengExpressionOperation);
  531. n := (aNew as TengExpressionOperation);
  532. if (n.Weight < o.Weight) then begin
  533. tmp := n.ExchangeFirst(o.ExchangeLast(n));
  534. aNew := nil;
  535. result := aOld;
  536. end else begin
  537. tmp := n.ExchangeFirst(o);
  538. aOld := nil;
  539. result := aNew;
  540. end;
  541. if Assigned(tmp) then
  542. raise EengExpressionInternal.Create(1, fParent);
  543. end else if (aOld is TengExpressionOperation) then begin
  544. o := (aOld as TengExpressionOperation);
  545. o.ExchangeLast(aNew);
  546. aNew := nil;
  547. result := aOld;
  548. end else if (aNew is TengExpressionOperation) then begin
  549. n := (aNew as TengExpressionOperation);
  550. n.ExchangeFirst(aOld);
  551. aOld := nil;
  552. result := aNew;
  553. end;;
  554. except
  555. FreeAndNil(aOld);
  556. FreeAndNil(aNew);
  557. result := nil;
  558. raise;
  559. end;
  560. end;
  561. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  562. function TExpressionParser.GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  563. var
  564. uOp: TengExpressionUnaryOperator;
  565. bOp: TengExpressionBinaryOperator;
  566. item: TengExpressionItem;
  567. param: TengTokenParameter;
  568. sr: TengSearchResults;
  569. walker: TengKeyValuePairSearchWalker;
  570. tmp: TengShaderPart;
  571. begin
  572. item := nil;
  573. result := nil;
  574. try
  575. if NextParam(param) then begin
  576. // GroupBegin
  577. if (param.Name = TOKEN_OP_GROUP_BEGIN) then begin
  578. if not (exGroupBegin in aExpected) then
  579. RaiseEx('unexpected', param);
  580. item := GetGroup;
  581. result := TengExpressionGroup.Create(Move(item), param.Col, param.Line);
  582. // GroupEnd
  583. end else if (param.Name = TOKEN_OP_GROUP_END) then begin
  584. if not (exGroupEnd in aExpected) then
  585. RaiseEx('unexpected', param);
  586. // UnaryOperation
  587. end else if IsUnaryOperation(param.Name, uOp) then begin
  588. if not (exUnaryOperation in aExpected) then
  589. RaiseEx('unexpected operation:', param);
  590. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  591. result := TengExpressionUnaryOperation.Create(uOp, Move(item), param.Line, param.Col);
  592. // BinaryOperation
  593. end else if IsBinaryOperation(param.Name, bOp) then begin
  594. if not (exBinaryOperation in aExpected) then
  595. RaiseEx('unexpected operation:', param);
  596. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  597. item := TengExpressionBinaryOperation.Create(bOp, nil, Move(item), param.Line, param.Col);
  598. result := Merge(result, item);
  599. // Value
  600. end else if param.Quoted and IsValidIdentifier(param.Name) then begin
  601. if not (exValue in aExpected) then
  602. RaiseEx('unexpected value:', param);
  603. result := TengExpressionValue.Create(param.Name, param.Line, param.Col);
  604. // Variable
  605. end else if IsValidIdentifier(param.Name) then begin
  606. if not (exVariable in aExpected) then
  607. RaiseEx('unexpected variable:', param);
  608. sr := TengSearchResults.Create;
  609. walker := TengKeyValuePairSearchWalker.Create(sr);
  610. try
  611. walker.Name := param.Name;
  612. walker.SearchFlags := [sfSearchChildren, sfSearchParents];
  613. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic);
  614. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope);
  615. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  616. walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile);
  617. walker.Run(fParent);
  618. tmp := ExtractSearchResult(fParent, param.Name, sr, [ifWarning, ifRaiseEx], param.Line, param.Col);
  619. result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col);
  620. finally
  621. FreeAndNil(walker);
  622. FreeAndNil(sr);
  623. end;
  624. // Unknown
  625. end else
  626. raise EengExpression.Create('invalid parameter: ' + param.Name, param.Line, param.Col, fParent.Filename, fParent);
  627. end;
  628. if not Assigned(result) and not (exGroupEnd in aExpected) then
  629. RaiseEx('unexpected', param, 'end');
  630. except
  631. FreeAndNil(item);
  632. FreeAndNil(result);
  633. raise;
  634. end;
  635. end;
  636. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  637. function TExpressionParser.GetGroup: TengExpressionItem;
  638. var
  639. ex: TExpectedParams;
  640. item: TengExpressionItem;
  641. b: Boolean;
  642. begin
  643. item := nil;
  644. result := nil;
  645. try
  646. ex := [exVariable, exValue, exGroupBegin, exUnaryOperation];
  647. repeat
  648. item := GetExpr(ex);
  649. b := Assigned(item);
  650. result := Merge(result, Move(item));
  651. ex := ex + [exBinaryOperation, exGroupEnd];
  652. until not b;
  653. except
  654. FreeAndNil(result);
  655. FreeAndNil(item);
  656. raise;
  657. end;
  658. end;
  659. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  660. constructor TExpressionParser.Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  661. begin
  662. fParamPos := aIndex - 1;
  663. fParams := aParams;
  664. fParent := aParent;
  665. end;
  666. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  667. function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  668. var
  669. parser: TExpressionParser;
  670. begin
  671. parser := TExpressionParser.Create(aParent, aParams, aIndex);
  672. try
  673. result := parser.GetGroup;
  674. finally
  675. FreeAndNil(parser);
  676. end;
  677. end;
  678. end.