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.

714 lines
29 KiB

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