tcexprparser.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. unit tcexprparser;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, testregistry, tcbaseparser, pastree;
  6. type
  7. { TTestExpressions }
  8. TTestExpressions= class(TTestParser)
  9. private
  10. FLeft: TPAsExpr;
  11. FRight: TPAsExpr;
  12. FTheExpr: TPasExpr;
  13. FVariables : TStringList;
  14. procedure AssertLeftPrecedence(AInnerLeft: Integer; AInnerOp: TExprOpCode;
  15. AInnerRight: Integer; AOuterOp: TexprOpCode; AOuterRight: Integer);
  16. procedure AssertRightPrecedence(AOuterLeft: Integer; AOuterOp: TExprOpCode;
  17. AInnerLeft: Integer; AInnerOp: TexprOpCode; AInnerRight: Integer);
  18. procedure DeclareVar(const AVarType: String; const AVarName: String = 'a');
  19. protected
  20. procedure SetUp; override;
  21. procedure TearDown; override;
  22. Procedure SetExpression(Const AExpression : String);
  23. Procedure ParseExpression;
  24. Procedure ParseExpression(Const AExpression : String);
  25. Function AssertBinaryExpr(Const Msg : String; Op : TExprOpCode; Out ALeft,ARight : TPasExpr) : TBinaryExpr;
  26. Function AssertBinaryExpr(Const Msg : String; AExpr : TPasExpr; Op : TExprOpCode; Out ALeft,ARight : TPasExpr) : TBinaryExpr;
  27. Function AssertUnaryExpr(Const Msg : String; Op : TExprOpCode; Out AOperand : TPasExpr) : TUnaryExpr;
  28. Function AssertUnaryExpr(Const Msg : String; AExpr: TPasExpr; Op : TExprOpCode; Out AOperand : TPasExpr) : TUnaryExpr;
  29. Property TheExpr : TPasExpr read FTheExpr;
  30. Property Theleft : TPAsExpr Read FLeft;
  31. Property TheRight : TPAsExpr Read FRight;
  32. published
  33. {
  34. TPasExprKind = (pekRange,
  35. pekListOfExp, );
  36. }
  37. procedure TestPrimitiveInteger;
  38. procedure TestPrimitiveIntegerHex;
  39. procedure TestPrimitiveIntegerOctal;
  40. procedure TestPrimitiveIntegerBinary;
  41. procedure TestPrimitiveDouble;
  42. procedure TestPrimitiveString;
  43. procedure TestPrimitiveIdent;
  44. procedure TestPrimitiveBooleanFalse;
  45. procedure TestPrimitiveBooleanTrue;
  46. procedure TestPrimitiveNil;
  47. procedure TestPrimitiveSet;
  48. procedure TestPrimitiveChar;
  49. procedure TestPrimitiveControlChar;
  50. procedure TestPrimitiveSetEmpty;
  51. procedure TestPrimitiveSelf;
  52. Procedure TestInherited;
  53. Procedure TestInheritedFunction;
  54. Procedure TestUnaryMinus;
  55. Procedure TestUnaryMinusWhiteSpace;
  56. Procedure TestUnaryAddress;
  57. Procedure TestUnaryNot;
  58. Procedure TestUnaryDeref;
  59. Procedure TestBinaryAdd;
  60. Procedure TestBinarySubtract;
  61. Procedure TestBinaryMultiply;
  62. Procedure TestBinaryDivision;
  63. Procedure TestBinaryPower;
  64. Procedure TestBinaryMod;
  65. Procedure TestBinaryDiv;
  66. procedure TestBinaryShl;
  67. procedure TestBinaryShr;
  68. Procedure TestBinarySymmetricalDifference;
  69. Procedure TestBinaryAnd;
  70. Procedure TestBinaryOr;
  71. Procedure TestBinaryXOr;
  72. Procedure TestBinaryIn;
  73. Procedure TestBinaryIs;
  74. Procedure TestBinaryAs;
  75. Procedure TestBinaryEquals;
  76. Procedure TestBinaryDiffers;
  77. Procedure TestBinaryLessThan;
  78. Procedure TestBinaryLessThanEqual;
  79. Procedure TestBinaryLargerThan;
  80. Procedure TestBinaryLargerThanEqual;
  81. procedure TestBinaryFullIdent;
  82. Procedure TestArrayElement;
  83. Procedure TestArrayElement2Dims;
  84. Procedure TestFunctionCall;
  85. Procedure TestFunctionCall2args;
  86. Procedure TestFunctionCallNoArgs;
  87. Procedure TestRange;
  88. Procedure TestBracketsTotal;
  89. Procedure TestBracketsLeft;
  90. Procedure TestBracketsRight;
  91. Procedure TestPrecedenceLeftToRight;
  92. Procedure TestPrecedenceLeftToRightMinus;
  93. Procedure TestPrecedenceLeftToRightMultiply;
  94. Procedure TestPrecedenceLeftToRightDivision;
  95. Procedure TestPrecedenceLeftToRightPlusMinus;
  96. Procedure TestPrecedenceLeftToRightMinusPlus;
  97. Procedure TestPrecedenceLeftToRightMultiplyDivision;
  98. Procedure TestPrecedenceLeftToRightDivisionMultiply;
  99. Procedure TestPrecedencePlusMultiply;
  100. Procedure TestPrecedencePlusDivide;
  101. Procedure TestPrecedenceMinusMultiply;
  102. Procedure TestPrecedenceMinusDivide;
  103. Procedure TestPrecedencePlusOr;
  104. Procedure TestPrecedenceAndOr;
  105. Procedure TestPrecedenceAndNot;
  106. Procedure TestPrecedencePlusAnd;
  107. Procedure TestPrecedenceMinusOr;
  108. Procedure TestPrecedenceMinusAnd;
  109. Procedure TestPrecedenceMultiplyOr;
  110. Procedure TestPrecedenceMultiplyAnd;
  111. Procedure TestPrecedencePlusDiv;
  112. Procedure TestPrecedencePlusMod;
  113. Procedure TestPrecedenceMultiplyDiv;
  114. Procedure TestPrecedenceDivMultiply;
  115. Procedure TestTypeCast;
  116. Procedure TestCreate;
  117. end;
  118. implementation
  119. procedure TTestExpressions.DeclareVar(const AVarType: String;
  120. const AVarName: String = 'a');
  121. begin
  122. FVariables.Add(AVarName+' : '+AVarType+';');
  123. end;
  124. procedure TTestExpressions.TestPrimitiveInteger;
  125. begin
  126. ParseExpression('1');
  127. AssertExpression('Simple integer',theExpr,pekNumber,'1');
  128. end;
  129. procedure TTestExpressions.TestPrimitiveIntegerHex;
  130. begin
  131. ParseExpression('$FF');
  132. AssertExpression('Simple integer',theExpr,pekNumber,'$FF');
  133. end;
  134. procedure TTestExpressions.TestPrimitiveIntegerOctal;
  135. begin
  136. ParseExpression('&777');
  137. AssertExpression('Simple integer',theExpr,pekNumber,'&777');
  138. end;
  139. procedure TTestExpressions.TestPrimitiveIntegerBinary;
  140. begin
  141. ParseExpression('%10101010');
  142. AssertExpression('Simple integer',theExpr,pekNumber,'%10101010');
  143. end;
  144. procedure TTestExpressions.TestPrimitiveDouble;
  145. begin
  146. ParseExpression('1.2');
  147. AssertExpression('Simple double',theExpr,pekNumber,'1.2');
  148. end;
  149. procedure TTestExpressions.TestPrimitiveString;
  150. begin
  151. DeclareVar('string');
  152. ParseExpression('''123''');
  153. AssertExpression('Simple string',theExpr,pekString,'''123''');
  154. end;
  155. procedure TTestExpressions.TestPrimitiveIdent;
  156. begin
  157. DeclareVar('integer','a');
  158. DeclareVar('integer','b');
  159. ParseExpression('b');
  160. AssertExpression('Simple identifier',theExpr,pekIdent,'b');
  161. end;
  162. procedure TTestExpressions.TestBinaryFullIdent;
  163. begin
  164. DeclareVar('integer','a');
  165. DeclareVar('record x,y : integer; end','b');
  166. ParseExpression('b.x');
  167. AssertBinaryExpr('sub identifier',eopSubIdent,Fleft,FRight);
  168. AssertExpression('Simple identifier',Theleft,pekIdent,'b');
  169. AssertExpression('Simple identifier',Theright,pekIdent,'x');
  170. end;
  171. procedure TTestExpressions.TestArrayElement;
  172. Var
  173. P : TParamsExpr;
  174. begin
  175. DeclareVar('integer','a');
  176. DeclareVar('array[1..2] of integer','b');
  177. ParseExpression('b[1]');
  178. P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekArrayParams,TParamsExpr));
  179. AssertExpression('Name of array',P.Value,pekIdent,'b');
  180. AssertEquals('One dimension',1,Length(p.params));
  181. AssertExpression('Simple identifier',p.params[0],pekNumber,'1');
  182. end;
  183. procedure TTestExpressions.TestArrayElement2Dims;
  184. Var
  185. P : TParamsExpr;
  186. begin
  187. DeclareVar('integer','a');
  188. DeclareVar('array[1..2,1..2] of integer','b');
  189. ParseExpression('b[1,2]');
  190. P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekArrayParams,TParamsExpr));
  191. AssertExpression('Name of array',P.Value,pekIdent,'b');
  192. AssertEquals('Two dimensions',2,Length(p.params));
  193. AssertExpression('Simple identifier',p.params[0],pekNumber,'1');
  194. AssertExpression('Simple identifier',p.params[1],pekNumber,'2');
  195. end;
  196. procedure TTestExpressions.TestFunctionCall;
  197. Var
  198. P : TParamsExpr;
  199. begin
  200. DeclareVar('integer','a');
  201. ParseExpression('Random(10)');
  202. P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekFuncParams,TParamsExpr));
  203. AssertExpression('Name of function',P.Value,pekIdent,'Random');
  204. AssertEquals('1 argument',1,Length(p.params));
  205. AssertExpression('Simple identifier',p.params[0],pekNumber,'10');
  206. end;
  207. procedure TTestExpressions.TestFunctionCall2args;
  208. Var
  209. P : TParamsExpr;
  210. begin
  211. DeclareVar('integer','a');
  212. ParseExpression('Random(10,12)');
  213. P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekFuncParams,TParamsExpr));
  214. AssertExpression('Name of function',P.Value,pekIdent,'Random');
  215. AssertEquals('2 argument',2,Length(p.params));
  216. AssertExpression('Simple identifier 1',p.params[0],pekNumber,'10');
  217. AssertExpression('Simple identifier 2',p.params[1],pekNumber,'12');
  218. end;
  219. procedure TTestExpressions.TestFunctionCallNoArgs;
  220. Var
  221. P : TParamsExpr;
  222. begin
  223. DeclareVar('integer','a');
  224. ParseExpression('Random()');
  225. P:=TParamsExpr(AssertExpression('Simple identifier',theExpr,pekFuncParams,TParamsExpr));
  226. AssertExpression('Name of function',P.Value,pekIdent,'Random');
  227. AssertEquals('0 arguments',0,Length(p.params));
  228. end;
  229. procedure TTestExpressions.TestRange;
  230. Var
  231. B : TBinaryExpr;
  232. begin
  233. DeclareVar('boolean','a');
  234. DeclareVar('byte','b');
  235. ParseExpression('b in 0..10');
  236. AssertBinaryExpr('Simple binary In',eopIn,FLeft,FRight);
  237. AssertExpression('Left is b',TheLeft,pekIdent,'b');
  238. B:=TBinaryExpr(AssertExpression('Right is range',TheRight,pekRange,TBinaryExpr));
  239. AssertExpression('Left is 0',B.Left,pekNumber,'0');
  240. AssertExpression('Right is 10',B.Right,pekNumber,'10');
  241. end;
  242. procedure TTestExpressions.TestBracketsTotal;
  243. begin
  244. DeclareVar('integer','a');
  245. ParseExpression('(3+4)');
  246. AssertBinaryExpr('simple binary add',eopAdd,FLeft,FRight);
  247. AssertExpression('Inner Left is 3',TheLeft,pekNumber,'3');
  248. AssertExpression('Inner Right is 4',TheRight,pekNumber,'4');
  249. end;
  250. procedure TTestExpressions.TestBracketsLeft;
  251. begin
  252. DeclareVar('integer','a');
  253. ParseExpression('2*(3+4)');
  254. AssertRightPrecedence(2,eopMultiply,3,eopAdd,4);
  255. end;
  256. procedure TTestExpressions.TestBracketsRight;
  257. begin
  258. DeclareVar('integer','a');
  259. ParseExpression('(2*3)+4');
  260. AssertLeftPrecedence(2,eopMultiply,3,eopAdd,4);
  261. end;
  262. procedure TTestExpressions.TestPrecedenceLeftToRight;
  263. begin
  264. ParseExpression('1+2+3');
  265. AssertLeftPrecedence(1,eopAdd,2,eopAdd,3);
  266. end;
  267. procedure TTestExpressions.TestPrecedenceLeftToRightMinus;
  268. begin
  269. ParseExpression('1-2-3');
  270. AssertLeftPrecedence(1,eopSubtract,2,eopSubtract,3);
  271. end;
  272. procedure TTestExpressions.TestPrecedenceLeftToRightMultiply;
  273. begin
  274. ParseExpression('1*2*3');
  275. AssertLeftPrecedence(1,eopMultiply,2,eopMultiply,3);
  276. end;
  277. procedure TTestExpressions.TestPrecedenceLeftToRightDivision;
  278. begin
  279. ParseExpression('1/2/3');
  280. AssertLeftPrecedence(1,eopDivide,2,eopDivide,3);
  281. end;
  282. procedure TTestExpressions.TestPrecedenceLeftToRightPlusMinus;
  283. begin
  284. ParseExpression('1+2-3');
  285. AssertLeftPrecedence(1,eopAdd,2,eopSubtract,3);
  286. end;
  287. procedure TTestExpressions.TestPrecedenceLeftToRightMinusPlus;
  288. begin
  289. ParseExpression('1-2+3');
  290. AssertLeftPrecedence(1,eopSubtract,2,eopAdd,3);
  291. end;
  292. procedure TTestExpressions.TestPrecedenceLeftToRightMultiplyDivision;
  293. begin
  294. ParseExpression('1*2/3');
  295. AssertLeftPrecedence(1,eopMultiply,2,eopDivide,3);
  296. end;
  297. procedure TTestExpressions.TestPrecedenceLeftToRightDivisionMultiply;
  298. begin
  299. ParseExpression('1/2*3');
  300. AssertLeftPrecedence(1,eopDivide,2,eopMultiply,3);
  301. end;
  302. procedure TTestExpressions.TestPrecedencePlusMultiply;
  303. begin
  304. ParseExpression('1+2*3');
  305. AssertRightPrecedence(1,eopAdd,2,eopMultiply,3);
  306. end;
  307. procedure TTestExpressions.TestPrecedencePlusDivide;
  308. begin
  309. ParseExpression('1+2/3');
  310. AssertRightPrecedence(1,eopAdd,2,eopDivide,3);
  311. end;
  312. procedure TTestExpressions.TestPrecedenceMinusMultiply;
  313. begin
  314. ParseExpression('1-2*3');
  315. AssertRightPrecedence(1,eopsubtract,2,eopMultiply,3);
  316. end;
  317. procedure TTestExpressions.TestPrecedenceMinusDivide;
  318. begin
  319. ParseExpression('1-2/3');
  320. AssertRightPrecedence(1,eopsubtract,2,eopDivide,3);
  321. end;
  322. procedure TTestExpressions.TestPrecedencePlusOr;
  323. begin
  324. ParseExpression('1 or 2 + 3');
  325. AssertLeftPrecedence(1,eopor,2,eopAdd,3);
  326. end;
  327. procedure TTestExpressions.TestPrecedenceAndOr;
  328. begin
  329. ParseExpression('1 or 2 and 3');
  330. AssertRightPrecedence(1,eopor,2,eopAnd,3);
  331. end;
  332. procedure TTestExpressions.TestPrecedenceAndNot;
  333. begin
  334. ParseExpression('Not 1 and 3');
  335. AssertBinaryExpr('Simple binary and',eopAnd,FLeft,FRight);
  336. AssertExpression('Outer right is 3',TheRight,pekNumber,'3');
  337. AssertUnaryExpr('Left is Unary not ',TheLeft,eopNot,FRight);
  338. AssertExpression('Inner Right is 1',TheRight,pekNumber,'1');
  339. end;
  340. procedure TTestExpressions.TestPrecedencePlusAnd;
  341. begin
  342. ParseExpression('1 + 2 and 3');
  343. AssertRightPrecedence(1,eopAdd,2,eopAnd,3);
  344. end;
  345. procedure TTestExpressions.TestPrecedenceMinusOr;
  346. begin
  347. ParseExpression('1 or 2 - 3');
  348. AssertLeftPrecedence(1,eopOr,2,eopSubtract,3);
  349. end;
  350. procedure TTestExpressions.TestPrecedenceMinusAnd;
  351. begin
  352. ParseExpression('1 - 2 and 3');
  353. AssertRightPrecedence(1,eopSubtract,2,eopand,3);
  354. end;
  355. procedure TTestExpressions.TestPrecedenceMultiplyOr;
  356. begin
  357. ParseExpression('1 or 2 * 3');
  358. AssertRightPrecedence(1,eopOr,2,eopMultiply,3);
  359. end;
  360. procedure TTestExpressions.TestPrecedenceMultiplyAnd;
  361. begin
  362. ParseExpression('1 * 2 and 3');
  363. AssertLeftPrecedence(1,eopMultiply,2,eopAnd,3);
  364. end;
  365. procedure TTestExpressions.TestPrecedencePlusDiv;
  366. begin
  367. ParseExpression('1+2 div 3');
  368. AssertRightPrecedence(1,eopAdd,2,eopDiv,3);
  369. end;
  370. procedure TTestExpressions.TestPrecedencePlusMod;
  371. begin
  372. ParseExpression('1+2 mod 3');
  373. AssertRightPrecedence(1,eopAdd,2,eopMod,3);
  374. end;
  375. procedure TTestExpressions.AssertLeftPrecedence(AInnerLeft : Integer; AInnerOp : TExprOpCode; AInnerRight : Integer; AOuterOp : TexprOpCode; AOuterRight: Integer);
  376. begin
  377. AssertBinaryExpr('Outer expression',AOuterOp,FLeft,FRight);
  378. AssertExpression('Outer right constant',TheRight,pekNumber,intToStr(AOuterRight));
  379. AssertBinaryExpr('Inner (left) expression',TheLeft,AInnerOp,FLeft,FRight);
  380. AssertExpression('Inner Left constant',TheLeft,pekNumber,IntToStr(AInnerLeft));
  381. AssertExpression('Inner Right constant',TheRight,pekNumber,IntToStr(AInnerRight));
  382. end;
  383. procedure TTestExpressions.AssertRightPrecedence(AOuterLeft : Integer; AOuterOp : TExprOpCode; AInnerLeft : Integer; AInnerOp : TexprOpCode; AInnerRight: Integer);
  384. begin
  385. AssertBinaryExpr('Outer expression',AOuterOp,FLeft,FRight);
  386. AssertExpression('Outer left constant',TheLeft,pekNumber,intToStr(AOuterLeft));
  387. AssertBinaryExpr('Inner (right) expression',TheRight,AInnerOp,FLeft,FRight);
  388. AssertExpression('Inner Left constant',TheLeft,pekNumber,IntToStr(AInnerLeft));
  389. AssertExpression('Inner Right constant',TheRight,pekNumber,IntToStr(AInnerRight));
  390. end;
  391. procedure TTestExpressions.TestPrecedenceMultiplyDiv;
  392. begin
  393. ParseExpression('1 * 2 div 3');
  394. AssertLeftPrecedence(1,eopMultiply,2,eopDiv,3);
  395. end;
  396. procedure TTestExpressions.TestPrecedenceDivMultiply;
  397. begin
  398. ParseExpression('1 div 2 * 3');
  399. AssertLeftPrecedence(1,eopDiv,2,eopMultiply,3);
  400. end;
  401. procedure TTestExpressions.TestTypeCast;
  402. begin
  403. DeclareVar('TSDOBaseDataObjectClass');
  404. ParseExpression('TSDOBaseDataObjectClass(Self.ClassType).Create');
  405. end;
  406. procedure TTestExpressions.TestCreate;
  407. begin
  408. DeclareVar('ESDOSerializationException');
  409. ParseExpression('ESDOSerializationException.CreateFmt(SERR_InvalidDataTypeInContext,[IntToStr(Ord(AOwner^.DataType))])');
  410. end;
  411. procedure TTestExpressions.TestUnaryMinus;
  412. begin
  413. DeclareVar('integer','a');
  414. DeclareVar('integer','b');
  415. ParseExpression('-b');
  416. AssertUnaryExpr('Simple minus unary',eopSubtract,FLeft);
  417. AssertExpression('Simple identifier',theLeft,pekIdent,'b');
  418. end;
  419. procedure TTestExpressions.TestUnaryMinusWhiteSpace;
  420. begin
  421. DeclareVar('integer','a');
  422. DeclareVar('integer','b');
  423. ParseExpression('- b');
  424. AssertUnaryExpr('Simple minus unary',eopSubtract,FLeft);
  425. AssertExpression('Simple identifier',theLeft,pekIdent,'b');
  426. end;
  427. procedure TTestExpressions.TestUnaryAddress;
  428. begin
  429. DeclareVar('integer','a');
  430. DeclareVar('integer','b');
  431. ParseExpression('@b');
  432. AssertUnaryExpr('Simple address unary',eopAddress,FLeft);
  433. AssertExpression('Simple identifier',theLeft,pekIdent,'b');
  434. end;
  435. procedure TTestExpressions.TestUnaryNot;
  436. begin
  437. DeclareVar('boolean','a');
  438. DeclareVar('boolean','b');
  439. ParseExpression('not b');
  440. AssertUnaryExpr('Simple address unary',eopNot,FLeft);
  441. AssertExpression('Simple identifier',theLeft,pekIdent,'b');
  442. end;
  443. procedure TTestExpressions.TestUnaryDeref;
  444. begin
  445. DeclareVar('integer','a');
  446. DeclareVar('pinteger','b');
  447. ParseExpression('b^');
  448. AssertUnaryExpr('Simple address unary',eopDeref,FLeft);
  449. AssertExpression('Simple identifier',theLeft,pekIdent,'b');
  450. end;
  451. procedure TTestExpressions.TestBinaryAdd;
  452. begin
  453. ParseExpression('1+2');
  454. AssertBinaryExpr('Simple binary add',eopAdd,FLeft,FRight);
  455. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  456. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  457. end;
  458. procedure TTestExpressions.TestBinarySubtract;
  459. begin
  460. ParseExpression('1-2');
  461. AssertBinaryExpr('Simple binary subtract',eopSubtract,FLeft,FRight);
  462. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  463. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  464. end;
  465. procedure TTestExpressions.TestBinaryMultiply;
  466. begin
  467. ParseExpression('1*2');
  468. AssertBinaryExpr('Simple binary multiply',eopMultiply,FLeft,FRight);
  469. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  470. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  471. end;
  472. procedure TTestExpressions.TestBinaryDivision;
  473. begin
  474. DeclareVar('double');
  475. ParseExpression('1/2');
  476. AssertBinaryExpr('Simple binary division',eopDivide,FLeft,FRight);
  477. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  478. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  479. end;
  480. procedure TTestExpressions.TestBinaryPower;
  481. begin
  482. DeclareVar('double');
  483. ParseExpression('1**2');
  484. AssertBinaryExpr('Simple binary power',eopPower,FLeft,FRight);
  485. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  486. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  487. end;
  488. procedure TTestExpressions.TestBinaryMod;
  489. begin
  490. ParseExpression('1 mod 2');
  491. AssertBinaryExpr('Simple binary mod',eopMod,FLeft,FRight);
  492. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  493. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  494. end;
  495. procedure TTestExpressions.TestBinaryDiv;
  496. begin
  497. ParseExpression('1 div 2');
  498. AssertBinaryExpr('Simple binary div',eopDiv,FLeft,FRight);
  499. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  500. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  501. end;
  502. procedure TTestExpressions.TestBinaryShl;
  503. begin
  504. ParseExpression('1 shl 2');
  505. AssertBinaryExpr('Simple binary shl',eopShl,FLeft,FRight);
  506. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  507. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  508. end;
  509. procedure TTestExpressions.TestBinaryShr;
  510. begin
  511. ParseExpression('1 shr 2');
  512. AssertBinaryExpr('Simple binary shr',eopShr,FLeft,FRight);
  513. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  514. AssertExpression('Right is 2',TheRight,pekNumber,'2');
  515. end;
  516. procedure TTestExpressions.TestBinarySymmetricalDifference;
  517. begin
  518. DeclareVar('Set of Byte','a');
  519. DeclareVar('Set of Byte','b');
  520. DeclareVar('Set of Byte','c');
  521. ParseExpression('b >< c');
  522. AssertBinaryExpr('Simple binary smmetrical difference',eopSymmetricalDifference,FLeft,FRight);
  523. AssertExpression('Left is b',TheLeft,pekident,'b');
  524. AssertExpression('Right is c',TheRight,pekIdent,'c');
  525. end;
  526. procedure TTestExpressions.TestBinaryAnd;
  527. begin
  528. DeclareVar('boolean','a');
  529. DeclareVar('boolean','b');
  530. DeclareVar('boolean','b');
  531. ParseExpression('b and c');
  532. AssertBinaryExpr('Simple binary and',eopAnd,FLeft,FRight);
  533. AssertExpression('Left is b',TheLeft,pekIdent,'b');
  534. AssertExpression('Right is c',TheRight,pekIdent,'c');
  535. end;
  536. procedure TTestExpressions.TestBinaryOr;
  537. begin
  538. DeclareVar('boolean','a');
  539. DeclareVar('boolean','b');
  540. DeclareVar('boolean','b');
  541. ParseExpression('b or c');
  542. AssertBinaryExpr('Simple binary or',eopOr,FLeft,FRight);
  543. AssertExpression('Left is b',TheLeft,pekIdent,'b');
  544. AssertExpression('Right is c',TheRight,pekIdent,'c');
  545. end;
  546. procedure TTestExpressions.TestBinaryXOr;
  547. begin
  548. DeclareVar('boolean','a');
  549. DeclareVar('boolean','b');
  550. DeclareVar('boolean','b');
  551. ParseExpression('b xor c');
  552. AssertBinaryExpr('Simple binary xor',eopxOr,FLeft,FRight);
  553. AssertExpression('Left is b',TheLeft,pekIdent,'b');
  554. AssertExpression('Right is c',TheRight,pekIdent,'c');
  555. end;
  556. procedure TTestExpressions.TestBinaryIn;
  557. begin
  558. DeclareVar('boolean','a');
  559. ParseExpression('1 in [1,2,3]');
  560. AssertBinaryExpr('Simple binary In',eopIn,FLeft,FRight);
  561. AssertExpression('Left is 1',TheLeft,pekNumber,'1');
  562. AssertExpression('Right is array set',TheRight,pekSet,TParamsExpr);
  563. end;
  564. procedure TTestExpressions.TestBinaryIs;
  565. begin
  566. DeclareVar('boolean','a');
  567. DeclareVar('TObject','b');
  568. ParseExpression('b is TObject');
  569. AssertBinaryExpr('Simple binary Is',eopIs,FLeft,FRight);
  570. AssertExpression('Left is 1',TheLeft,pekident,'b');
  571. AssertExpression('Right is TObject',TheRight,pekIdent,'TObject');
  572. end;
  573. procedure TTestExpressions.TestBinaryAs;
  574. begin
  575. DeclareVar('TObject','a');
  576. DeclareVar('TObject','b');
  577. ParseExpression('b as TObject');
  578. AssertBinaryExpr('Simple binary As',eopAs,FLeft,FRight);
  579. AssertExpression('Left is 1',TheLeft,pekident,'b');
  580. AssertExpression('Right is TObject',TheRight,pekIdent,'TObject');
  581. end;
  582. procedure TTestExpressions.TestBinaryEquals;
  583. begin
  584. DeclareVar('boolean','a');
  585. DeclareVar('integer','b');
  586. DeclareVar('integer','c');
  587. ParseExpression('b=c');
  588. AssertBinaryExpr('Simple binary equals',eopEqual,FLeft,FRight);
  589. AssertExpression('Left is b',TheLeft,pekident,'b');
  590. AssertExpression('Right is c',TheRight,pekIdent,'c');
  591. end;
  592. procedure TTestExpressions.TestBinaryDiffers;
  593. begin
  594. DeclareVar('boolean','a');
  595. DeclareVar('integer','b');
  596. DeclareVar('integer','c');
  597. ParseExpression('b<>c');
  598. AssertBinaryExpr('Simple binary differs',eopNotEqual,FLeft,FRight);
  599. AssertExpression('Left is b',TheLeft,pekident,'b');
  600. AssertExpression('Right is c',TheRight,pekIdent,'c');
  601. end;
  602. procedure TTestExpressions.TestBinaryLessThan;
  603. begin
  604. DeclareVar('boolean','a');
  605. DeclareVar('integer','b');
  606. DeclareVar('integer','c');
  607. ParseExpression('b<c');
  608. AssertBinaryExpr('Simple binary less than',eopLessThan,FLeft,FRight);
  609. AssertExpression('Left is b',TheLeft,pekident,'b');
  610. AssertExpression('Right is c',TheRight,pekIdent,'c');
  611. end;
  612. procedure TTestExpressions.TestBinaryLessThanEqual;
  613. begin
  614. DeclareVar('boolean','a');
  615. DeclareVar('integer','b');
  616. DeclareVar('integer','c');
  617. ParseExpression('b<=c');
  618. AssertBinaryExpr('Simple binary less than or equal',eopLessThanEqual,FLeft,FRight);
  619. AssertExpression('Left is b',TheLeft,pekident,'b');
  620. AssertExpression('Right is c',TheRight,pekIdent,'c');
  621. end;
  622. procedure TTestExpressions.TestBinaryLargerThan;
  623. begin
  624. DeclareVar('boolean','a');
  625. DeclareVar('integer','b');
  626. DeclareVar('integer','c');
  627. ParseExpression('b>c');
  628. AssertBinaryExpr('Simple binary larger than ',eopGreaterThan,FLeft,FRight);
  629. AssertExpression('Left is b',TheLeft,pekident,'b');
  630. AssertExpression('Right is c',TheRight,pekIdent,'c');
  631. end;
  632. procedure TTestExpressions.TestBinaryLargerThanEqual;
  633. begin
  634. DeclareVar('boolean','a');
  635. DeclareVar('integer','b');
  636. DeclareVar('integer','c');
  637. ParseExpression('b>=c');
  638. AssertBinaryExpr('Simple binary larger than or equal',eopGreaterThanEqual,FLeft,FRight);
  639. AssertExpression('Left is b',TheLeft,pekident,'b');
  640. AssertExpression('Right is c',TheRight,pekIdent,'c');
  641. end;
  642. procedure TTestExpressions.TestPrimitiveBooleanFalse;
  643. begin
  644. DeclareVar('boolean','a');
  645. ParseExpression('False');
  646. AssertExpression('Simple boolean',theExpr,pekBoolConst,TBoolConstExpr);
  647. AssertEquals('Boolean false',False,TBoolConstExpr(TheExpr).Value);
  648. end;
  649. procedure TTestExpressions.TestPrimitiveBooleanTrue;
  650. begin
  651. DeclareVar('boolean','a');
  652. ParseExpression('True');
  653. AssertExpression('Simple boolean',theExpr,pekBoolConst,TBoolConstExpr);
  654. AssertEquals('Boolean true',True,TBoolConstExpr(TheExpr).Value);
  655. end;
  656. procedure TTestExpressions.TestPrimitiveNil;
  657. begin
  658. DeclareVar('pointer','a');
  659. ParseExpression('Nil');
  660. AssertExpression('Nil expr',theExpr,pekNil,TNilExpr);
  661. end;
  662. procedure TTestExpressions.TestPrimitiveSet;
  663. Var
  664. P : TParamsExpr;
  665. begin
  666. DeclareVar('set of byte','a');
  667. ParseExpression('[1,2,3]');
  668. P:=TParamsExpr(AssertExpression('Set expr',theExpr,pekSet,TParamsExpr));
  669. AssertEquals('Element count',3,Length(P.Params));
  670. AssertExpression('Element 1 in set',P.Params[0],pekNumber,'1');
  671. AssertExpression('Element 2 in set',P.Params[1],pekNumber,'2');
  672. AssertExpression('Element 3 in set',P.Params[2],pekNumber,'3');
  673. end;
  674. procedure TTestExpressions.TestPrimitiveChar;
  675. begin
  676. DeclareVar('char');
  677. ParseExpression('#32');
  678. AssertExpression('Simple string',theExpr,pekString,'#32');
  679. end;
  680. procedure TTestExpressions.TestPrimitiveControlChar;
  681. begin
  682. DeclareVar('char');
  683. ParseExpression('^M');
  684. AssertExpression('Simple string',theExpr,pekString,'^M');
  685. end;
  686. procedure TTestExpressions.TestPrimitiveSetEmpty;
  687. Var
  688. P : TParamsExpr;
  689. begin
  690. DeclareVar('set of byte','a');
  691. ParseExpression('[]');
  692. P:=TParamsExpr(AssertExpression('Set expr',theExpr,pekSet,TParamsExpr));
  693. AssertEquals('Element count',0,Length(P.Params));
  694. end;
  695. procedure TTestExpressions.TestPrimitiveSelf;
  696. begin
  697. DeclareVar('pointer','a');
  698. ParseExpression('Self');
  699. AssertExpression('Inherited expr',theExpr,pekSelf,TSelfExpr);
  700. end;
  701. procedure TTestExpressions.TestInherited;
  702. begin
  703. DeclareVar('pointer','a');
  704. ParseExpression('inherited');
  705. AssertExpression('Inherited expr',theExpr,pekInherited,TInheritedExpr);
  706. end;
  707. procedure TTestExpressions.TestInheritedFunction;
  708. begin
  709. DeclareVar('pointer','a');
  710. ParseExpression('inherited myfunction');
  711. AssertBinaryExpr('Inherited expr',eopNone,Fleft,FRight);
  712. AssertExpression('Inherited expr',theleft,pekInherited,TInheritedExpr);
  713. AssertExpression('Inherited expr',theright,pekIdent,'myfunction');
  714. end;
  715. procedure TTestExpressions.SetUp;
  716. begin
  717. Inherited;
  718. FVariables:=TStringList.Create;
  719. end;
  720. procedure TTestExpressions.TearDown;
  721. begin
  722. FreeAndNil(FVariables);
  723. Inherited;
  724. end;
  725. procedure TTestExpressions.SetExpression(const AExpression: String);
  726. Var
  727. I : Integer;
  728. begin
  729. StartProgram('afile');
  730. if FVariables.Count=0 then
  731. DeclareVar('integer');
  732. Add('Var');
  733. For I:=0 to FVariables.Count-1 do
  734. Add(' '+Fvariables[I]);
  735. Add('begin');
  736. Add(' a:='+AExpression+';');
  737. end;
  738. procedure TTestExpressions.ParseExpression;
  739. begin
  740. ParseModule;
  741. AssertEquals('Have program',TPasProgram,Module.ClassType);
  742. AssertNotNull('Have program section',PasProgram.ProgramSection);
  743. AssertNotNull('Have initialization section',PasProgram.InitializationSection);
  744. AssertEquals('Have initialization statement',1,PasProgram.InitializationSection.Elements.Count);
  745. AssertNotNull('Have initialization statement',PasProgram.InitializationSection.Elements[0]);
  746. AssertEquals('Assignment statement',TPasImplAssign,TObject(PasProgram.InitializationSection.Elements[0]).ClassType);
  747. FTheExpr:=TPasImplAssign(PasProgram.InitializationSection.Elements[0]).right;
  748. AssertNotNull('Have assignment expression',FTheExpr);
  749. end;
  750. procedure TTestExpressions.ParseExpression(const AExpression: String);
  751. begin
  752. SetExpression(AExpression);
  753. ParseExpression;
  754. end;
  755. function TTestExpressions.AssertBinaryExpr(const Msg: String; Op: TExprOpCode;
  756. out ALeft, ARight: TPasExpr): TBinaryExpr;
  757. begin
  758. Result:=AssertBinaryExpr(Msg,TheExpr,Op,ALeft,ARight);
  759. end;
  760. function TTestExpressions.AssertBinaryExpr(const Msg: String; AExpr: TPasExpr;
  761. Op: TExprOpCode; out ALeft, ARight: TPasExpr): TBinaryExpr;
  762. begin
  763. AssertExpression(Msg+' is binary',AExpr,pekBinary,TBinaryExpr);
  764. Result:=AExpr as TBinaryExpr;
  765. AssertEquals(Msg+' opcode OK',Op,Result.OpCode);
  766. ALeft:=Result.Left;
  767. ARight:=Result.Right;
  768. AssertNotNull('Have left',ALeft);
  769. AssertNotNull('Have right',ARight);
  770. end;
  771. function TTestExpressions.AssertUnaryExpr(const Msg: String; Op: TExprOpCode;
  772. out AOperand : TPasExpr): TUnaryExpr;
  773. begin
  774. Result:=AssertUnaryExpr(Msg,TheExpr,OP,AOperand);
  775. end;
  776. function TTestExpressions.AssertUnaryExpr(const Msg: String; AExpr: TPasExpr;
  777. Op: TExprOpCode; out AOperand: TPasExpr): TUnaryExpr;
  778. begin
  779. AssertExpression(Msg+' is unary',AExpr,pekUnary,TUnaryExpr);
  780. Result:=AExpr as TUnaryExpr;
  781. AssertEquals(Msg+' opcode OK',Op,Result.OpCode);
  782. AOperand:=Result.Operand;
  783. AssertNotNull('Have left',AOperand);
  784. end;
  785. initialization
  786. RegisterTest(TTestExpressions);
  787. end.