tcbaseparser.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. unit tcbaseparser;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, pastree, pscanner, pparser, testregistry;
  6. const
  7. MainFilename = 'afile.pp';
  8. Type
  9. { TTestEngine }
  10. TTestEngine = Class(TPasTreeContainer)
  11. Private
  12. FList : TFPList;
  13. public
  14. Destructor Destroy; override;
  15. function CreateElement(AClass: TPTreeElement; const AName: String;
  16. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  17. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  18. override;
  19. function FindElement(const AName: String): TPasElement; override;
  20. end;
  21. TTestPasParser = Class(TPasParser);
  22. { TTestParser }
  23. TTestParser = class(TTestCase)
  24. Private
  25. FDeclarations: TPasDeclarations;
  26. FDefinition: TPasElement;
  27. FEngine : TPasTreeContainer;
  28. FModule: TPasModule;
  29. FParseResult: TPasElement;
  30. FScanner : TPascalScanner;
  31. FResolver : TStreamResolver;
  32. FParser : TTestPasParser;
  33. FSource: TStrings;
  34. FFileName : string;
  35. FIsUnit : Boolean;
  36. FImplementation : Boolean;
  37. FEndSource: Boolean;
  38. FUseImplementation: Boolean;
  39. function GetPL: TPasLibrary;
  40. function GetPP: TPasProgram;
  41. procedure CleanupParser;
  42. procedure SetupParser;
  43. protected
  44. procedure SetUp; override;
  45. procedure TearDown; override;
  46. procedure CreateEngine(var TheEngine: TPasTreeContainer); virtual;
  47. Procedure StartUnit(AUnitName : String);
  48. Procedure StartProgram(AFileName : String; AIn : String = ''; AOut : String = '');
  49. Procedure StartLibrary(AFileName : String);
  50. Procedure UsesClause(Units : Array of string);
  51. Procedure StartImplementation;
  52. Procedure EndSource;
  53. Procedure Add(Const ALine : String);
  54. Procedure Add(Const Lines : array of String);
  55. Procedure StartParsing;
  56. Procedure ParseDeclarations;
  57. Procedure ParseModule;
  58. procedure ResetParser;
  59. Procedure CheckHint(AHint : TPasMemberHint);
  60. Function AssertExpression(Const Msg: String; AExpr : TPasExpr; aKind : TPasExprKind; AClass : TClass) : TPasExpr;
  61. Function AssertExpression(Const Msg: String; AExpr : TPasExpr; aKind : TPasExprKind; AValue : String) : TPrimitiveExpr;
  62. Procedure AssertExportSymbol(Const Msg: String; AIndex : Integer; AName,AExportName : String; AExportIndex : Integer = -1);
  63. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasExprKind); overload;
  64. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TLoopType); overload;
  65. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasObjKind); overload;
  66. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TexprOpcode); overload;
  67. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasMemberHint); overload;
  68. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TCallingConvention); overload;
  69. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TArgumentAccess); overload;
  70. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TVariableModifier); overload;
  71. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TVariableModifiers); overload;
  72. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TPasMemberVisibility); overload;
  73. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TProcedureModifier); overload;
  74. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TProcedureModifiers); overload;
  75. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TProcTypeModifiers); overload;
  76. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TAssignKind); overload;
  77. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TProcedureMessageType); overload;
  78. Procedure AssertEquals(Const Msg : String; AExpected, AActual: TOperatorType); overload;
  79. Procedure AssertSame(Const Msg : String; AExpected, AActual: TPasElement); overload;
  80. Procedure HaveHint(AHint : TPasMemberHint; AHints : TPasMemberHints);
  81. Property Resolver : TStreamResolver Read FResolver;
  82. Property Scanner : TPascalScanner Read FScanner;
  83. Property Engine : TPasTreeContainer read FEngine;
  84. Property Parser : TTestPasParser read FParser ;
  85. Property Source : TStrings Read FSource;
  86. Property Module : TPasModule Read FModule;
  87. Property PasProgram : TPasProgram Read GetPP;
  88. Property PasLibrary : TPasLibrary Read GetPL;
  89. Property Declarations : TPasDeclarations read FDeclarations Write FDeclarations;
  90. Property Definition : TPasElement Read FDefinition Write FDefinition;
  91. // If set, Will be freed in teardown
  92. Property ParseResult : TPasElement Read FParseResult Write FParseResult;
  93. Property UseImplementation : Boolean Read FUseImplementation Write FUseImplementation;
  94. end;
  95. function ExtractFileUnitName(aFilename: string): string;
  96. function GetPasElementDesc(El: TPasElement): string;
  97. procedure ReadNextPascalToken(var Position: PChar; out TokenStart: PChar;
  98. NestedComments: boolean; SkipDirectives: boolean);
  99. implementation
  100. uses typinfo;
  101. function ExtractFileUnitName(aFilename: string): string;
  102. var
  103. p: Integer;
  104. begin
  105. Result:=ExtractFileName(aFilename);
  106. if Result='' then exit;
  107. for p:=length(Result) downto 1 do
  108. case Result[p] of
  109. '/','\': exit;
  110. '.':
  111. begin
  112. Delete(Result,p,length(Result));
  113. exit;
  114. end;
  115. end;
  116. end;
  117. function GetPasElementDesc(El: TPasElement): string;
  118. begin
  119. if El=nil then exit('nil');
  120. Result:=El.Name+':'+El.ClassName+'['+El.SourceFilename+','+IntToStr(El.SourceLinenumber)+']';
  121. end;
  122. procedure ReadNextPascalToken(var Position: PChar; out TokenStart: PChar;
  123. NestedComments: boolean; SkipDirectives: boolean);
  124. const
  125. IdentChars = ['a'..'z','A'..'Z','_','0'..'9'];
  126. HexNumberChars = ['0'..'9','a'..'f','A'..'F'];
  127. var
  128. c1:char;
  129. CommentLvl: Integer;
  130. Src: PChar;
  131. begin
  132. Src:=Position;
  133. // read till next atom
  134. while true do
  135. begin
  136. case Src^ of
  137. #0: break;
  138. #1..#32: // spaces and special characters
  139. inc(Src);
  140. #$EF:
  141. if (Src[1]=#$BB)
  142. and (Src[2]=#$BF) then
  143. begin
  144. // skip UTF BOM
  145. inc(Src,3);
  146. end
  147. else
  148. break;
  149. '{': // comment start or compiler directive
  150. if (Src[1]='$') and (not SkipDirectives) then
  151. // compiler directive
  152. break
  153. else begin
  154. // Pascal comment => skip
  155. CommentLvl:=1;
  156. while true do
  157. begin
  158. inc(Src);
  159. case Src^ of
  160. #0: break;
  161. '{':
  162. if NestedComments then
  163. inc(CommentLvl);
  164. '}':
  165. begin
  166. dec(CommentLvl);
  167. if CommentLvl=0 then
  168. begin
  169. inc(Src);
  170. break;
  171. end;
  172. end;
  173. end;
  174. end;
  175. end;
  176. '/': // comment or real division
  177. if (Src[1]='/') then
  178. begin
  179. // comment start -> read til line end
  180. inc(Src);
  181. while not (Src^ in [#0,#10,#13]) do
  182. inc(Src);
  183. end
  184. else
  185. break;
  186. '(': // comment, bracket or compiler directive
  187. if (Src[1]='*') then
  188. begin
  189. if (Src[2]='$') and (not SkipDirectives) then
  190. // compiler directive
  191. break
  192. else
  193. begin
  194. // comment start -> read til comment end
  195. inc(Src,2);
  196. CommentLvl:=1;
  197. while true do
  198. begin
  199. case Src^ of
  200. #0: break;
  201. '(':
  202. if NestedComments and (Src[1]='*') then
  203. inc(CommentLvl);
  204. '*':
  205. if (Src[1]=')') then
  206. begin
  207. dec(CommentLvl);
  208. if CommentLvl=0 then
  209. begin
  210. inc(Src,2);
  211. break;
  212. end;
  213. inc(Position);
  214. end;
  215. end;
  216. inc(Src);
  217. end;
  218. end;
  219. end else
  220. // round bracket open
  221. break;
  222. else
  223. break;
  224. end;
  225. end;
  226. // read token
  227. TokenStart:=Src;
  228. c1:=Src^;
  229. case c1 of
  230. #0:
  231. ;
  232. 'A'..'Z','a'..'z','_':
  233. begin
  234. // identifier
  235. inc(Src);
  236. while Src^ in IdentChars do
  237. inc(Src);
  238. end;
  239. '0'..'9': // number
  240. begin
  241. inc(Src);
  242. // read numbers
  243. while (Src^ in ['0'..'9']) do
  244. inc(Src);
  245. if (Src^='.') and (Src[1]<>'.') then
  246. begin
  247. // real type number
  248. inc(Src);
  249. while (Src^ in ['0'..'9']) do
  250. inc(Src);
  251. end;
  252. if (Src^ in ['e','E']) then
  253. begin
  254. // read exponent
  255. inc(Src);
  256. if (Src^='-') then inc(Src);
  257. while (Src^ in ['0'..'9']) do
  258. inc(Src);
  259. end;
  260. end;
  261. '''','#': // string constant
  262. while true do
  263. case Src^ of
  264. #0: break;
  265. '#':
  266. begin
  267. inc(Src);
  268. while Src^ in ['0'..'9'] do
  269. inc(Src);
  270. end;
  271. '''':
  272. begin
  273. inc(Src);
  274. while not (Src^ in ['''',#0]) do
  275. inc(Src);
  276. if Src^='''' then
  277. inc(Src);
  278. end;
  279. else
  280. break;
  281. end;
  282. '$': // hex constant
  283. begin
  284. inc(Src);
  285. while Src^ in HexNumberChars do
  286. inc(Src);
  287. end;
  288. '&': // octal constant or keyword as identifier (e.g. &label)
  289. begin
  290. inc(Src);
  291. if Src^ in ['0'..'7'] then
  292. while Src^ in ['0'..'7'] do
  293. inc(Src)
  294. else
  295. while Src^ in IdentChars do
  296. inc(Src);
  297. end;
  298. '{': // compiler directive (it can't be a comment, because see above)
  299. begin
  300. CommentLvl:=1;
  301. while true do
  302. begin
  303. inc(Src);
  304. case Src^ of
  305. #0: break;
  306. '{':
  307. if NestedComments then
  308. inc(CommentLvl);
  309. '}':
  310. begin
  311. dec(CommentLvl);
  312. if CommentLvl=0 then
  313. begin
  314. inc(Src);
  315. break;
  316. end;
  317. end;
  318. end;
  319. end;
  320. end;
  321. '(': // bracket or compiler directive
  322. if (Src[1]='*') then
  323. begin
  324. // compiler directive -> read til comment end
  325. inc(Src,2);
  326. while (Src^<>#0) and ((Src^<>'*') or (Src[1]<>')')) do
  327. inc(Src);
  328. inc(Src,2);
  329. end
  330. else
  331. // round bracket open
  332. inc(Src);
  333. #192..#255:
  334. begin
  335. // read UTF8 character
  336. inc(Src);
  337. if ((ord(c1) and %11100000) = %11000000) then
  338. begin
  339. // could be 2 byte character
  340. if (ord(Src[0]) and %11000000) = %10000000 then
  341. inc(Src);
  342. end
  343. else if ((ord(c1) and %11110000) = %11100000) then
  344. begin
  345. // could be 3 byte character
  346. if ((ord(Src[0]) and %11000000) = %10000000)
  347. and ((ord(Src[1]) and %11000000) = %10000000) then
  348. inc(Src,2);
  349. end
  350. else if ((ord(c1) and %11111000) = %11110000) then
  351. begin
  352. // could be 4 byte character
  353. if ((ord(Src[0]) and %11000000) = %10000000)
  354. and ((ord(Src[1]) and %11000000) = %10000000)
  355. and ((ord(Src[2]) and %11000000) = %10000000) then
  356. inc(Src,3);
  357. end;
  358. end;
  359. else
  360. inc(Src);
  361. case c1 of
  362. '<': if Src^ in ['>','='] then inc(Src);
  363. '.': if Src^='.' then inc(Src);
  364. '@':
  365. if Src^='@' then
  366. begin
  367. // @@ label
  368. repeat
  369. inc(Src);
  370. until not (Src^ in IdentChars);
  371. end
  372. else
  373. if (Src^='=') and (c1 in [':','+','-','/','*','<','>']) then
  374. inc(Src);
  375. end;
  376. end;
  377. Position:=Src;
  378. end;
  379. { TTestEngine }
  380. destructor TTestEngine.Destroy;
  381. begin
  382. FreeAndNil(FList);
  383. inherited Destroy;
  384. end;
  385. function TTestEngine.CreateElement(AClass: TPTreeElement; const AName: String;
  386. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  387. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  388. begin
  389. Result := AClass.Create(AName, AParent);
  390. Result.Visibility := AVisibility;
  391. Result.SourceFilename := ASourceFilename;
  392. Result.SourceLinenumber := ASourceLinenumber;
  393. if NeedComments and Assigned(CurrentParser) then
  394. begin
  395. // Writeln('Saving comment : ',CurrentParser.SavedComments);
  396. Result.DocComment:=CurrentParser.SavedComments;
  397. end;
  398. If not Assigned(FList) then
  399. FList:=TFPList.Create;
  400. FList.Add(Result);
  401. end;
  402. function TTestEngine.FindElement(const AName: String): TPasElement;
  403. Var
  404. I : Integer;
  405. begin
  406. Result:=Nil;
  407. if Assigned(FList) then
  408. begin
  409. I:=FList.Count-1;
  410. While (Result=Nil) and (I>=0) do
  411. begin
  412. if CompareText(TPasElement(FList[I]).Name,AName)=0 then
  413. Result:=TPasElement(Flist[i]);
  414. Dec(i);
  415. end;
  416. end;
  417. end;
  418. function TTestParser.GetPP: TPasProgram;
  419. begin
  420. Result:=Module as TPasProgram;
  421. end;
  422. function TTestParser.GetPL: TPasLibrary;
  423. begin
  424. Result:=Module as TPasLibrary;
  425. end;
  426. procedure TTestParser.SetupParser;
  427. begin
  428. FResolver:=TStreamResolver.Create;
  429. FResolver.OwnsStreams:=True;
  430. FScanner:=TPascalScanner.Create(FResolver);
  431. CreateEngine(FEngine);
  432. FParser:=TTestPasParser.Create(FScanner,FResolver,FEngine);
  433. FSource:=TStringList.Create;
  434. FModule:=Nil;
  435. FDeclarations:=Nil;
  436. FEndSource:=False;
  437. FImplementation:=False;
  438. FIsUnit:=False;
  439. end;
  440. procedure TTestParser.CleanupParser;
  441. begin
  442. {$IFDEF VerbosePasResolverMem}
  443. writeln('TTestParser.CleanupParser START');
  444. {$ENDIF}
  445. if Not Assigned(FModule) then
  446. FreeAndNil(FDeclarations)
  447. else
  448. FDeclarations:=Nil;
  449. FImplementation:=False;
  450. FEndSource:=False;
  451. FIsUnit:=False;
  452. {$IFDEF VerbosePasResolverMem}
  453. writeln('TTestParser.CleanupParser FModule');
  454. {$ENDIF}
  455. if Assigned(FModule) then
  456. ReleaseAndNil(TPasElement(FModule));
  457. {$IFDEF VerbosePasResolverMem}
  458. writeln('TTestParser.CleanupParser FSource');
  459. {$ENDIF}
  460. FreeAndNil(FSource);
  461. {$IFDEF VerbosePasResolverMem}
  462. writeln('TTestParser.CleanupParser FParseResult');
  463. {$ENDIF}
  464. FreeAndNil(FParseResult);
  465. {$IFDEF VerbosePasResolverMem}
  466. writeln('TTestParser.CleanupParser FParser');
  467. {$ENDIF}
  468. FreeAndNil(FParser);
  469. {$IFDEF VerbosePasResolverMem}
  470. writeln('TTestParser.CleanupParser FEngine');
  471. {$ENDIF}
  472. FreeAndNil(FEngine);
  473. {$IFDEF VerbosePasResolverMem}
  474. writeln('TTestParser.CleanupParser FScanner');
  475. {$ENDIF}
  476. FreeAndNil(FScanner);
  477. {$IFDEF VerbosePasResolverMem}
  478. writeln('TTestParser.CleanupParser FResolver');
  479. {$ENDIF}
  480. FreeAndNil(FResolver);
  481. {$IFDEF VerbosePasResolverMem}
  482. writeln('TTestParser.CleanupParser END');
  483. {$ENDIF}
  484. end;
  485. procedure TTestParser.ResetParser;
  486. begin
  487. CleanupParser;
  488. SetupParser;
  489. end;
  490. procedure TTestParser.SetUp;
  491. begin
  492. Inherited;
  493. SetupParser;
  494. end;
  495. procedure TTestParser.TearDown;
  496. begin
  497. {$IFDEF VerbosePasResolverMem}
  498. writeln('TTestParser.TearDown START CleanupParser');
  499. {$ENDIF}
  500. CleanupParser;
  501. {$IFDEF VerbosePasResolverMem}
  502. writeln('TTestParser.TearDown inherited');
  503. {$ENDIF}
  504. Inherited;
  505. {$IFDEF VerbosePasResolverMem}
  506. writeln('TTestParser.TearDown END');
  507. {$ENDIF}
  508. end;
  509. procedure TTestParser.CreateEngine(var TheEngine: TPasTreeContainer);
  510. begin
  511. TheEngine:=TTestEngine.Create;
  512. end;
  513. procedure TTestParser.StartUnit(AUnitName: String);
  514. begin
  515. FIsUnit:=True;
  516. If (AUnitName='') then
  517. AUnitName:=ExtractFileUnitName(MainFilename);
  518. Add('unit '+aUnitName+';');
  519. Add('');
  520. Add('interface');
  521. Add('');
  522. FFileName:=AUnitName+'.pp';
  523. end;
  524. procedure TTestParser.StartProgram(AFileName : String; AIn : String = ''; AOut : String = '');
  525. begin
  526. FIsUnit:=False;
  527. If (AFileName='') then
  528. AFileName:='proga';
  529. FFileName:=AFileName+'.pp';
  530. If (AIn<>'') then
  531. begin
  532. AFileName:=AFileName+'('+AIn;
  533. if (AOut<>'') then
  534. AFileName:=AFileName+','+AOut;
  535. AFileName:=AFileName+')';
  536. end;
  537. Add('program '+AFileName+';');
  538. FImplementation:=True;
  539. end;
  540. procedure TTestParser.StartLibrary(AFileName: String);
  541. begin
  542. FIsUnit:=False;
  543. If (AFileName='') then
  544. AFileName:='liba';
  545. FFileName:=AFileName+'.pp';
  546. Add('library '+AFileName+';');
  547. FImplementation:=True;
  548. end;
  549. procedure TTestParser.UsesClause(Units: array of string);
  550. Var
  551. S : String;
  552. I : integer;
  553. begin
  554. S:='';
  555. For I:=Low(units) to High(units) do
  556. begin
  557. If (S<>'') then
  558. S:=S+', ';
  559. S:=S+Units[i];
  560. end;
  561. Add('uses '+S+';');
  562. Add('');
  563. end;
  564. procedure TTestParser.StartImplementation;
  565. begin
  566. if Not FImplementation then
  567. begin
  568. if UseImplementation then
  569. begin
  570. FSource.Insert(0,'');
  571. FSource.Insert(0,'Implementation');
  572. FSource.Insert(0,'');
  573. end
  574. else
  575. begin
  576. Add('');
  577. Add('Implementation');
  578. Add('');
  579. end;
  580. FImplementation:=True;
  581. end;
  582. end;
  583. procedure TTestParser.EndSource;
  584. begin
  585. if Not FEndSource then
  586. begin
  587. Add('end.');
  588. FEndSource:=True;
  589. end;
  590. end;
  591. procedure TTestParser.Add(const ALine: String);
  592. begin
  593. FSource.Add(ALine);
  594. end;
  595. procedure TTestParser.Add(const Lines: array of String);
  596. var
  597. i: Integer;
  598. begin
  599. for i:=Low(Lines) to High(Lines) do
  600. Add(Lines[i]);
  601. end;
  602. procedure TTestParser.StartParsing;
  603. var
  604. i: Integer;
  605. begin
  606. If FIsUnit then
  607. StartImplementation;
  608. EndSource;
  609. If (FFileName='') then
  610. FFileName:=MainFilename;
  611. FResolver.AddStream(FFileName,TStringStream.Create(FSource.Text));
  612. FScanner.OpenFile(FFileName);
  613. Writeln('// Test : ',Self.TestName);
  614. for i:=0 to FSource.Count-1 do
  615. Writeln(Format('%:4d: ',[i+1]),FSource[i]);
  616. end;
  617. procedure TTestParser.ParseDeclarations;
  618. begin
  619. if UseImplementation then
  620. StartImplementation;
  621. FSource.Insert(0,'');
  622. FSource.Insert(0,'interface');
  623. FSource.Insert(0,'');
  624. FSource.Insert(0,'unit afile;');
  625. if Not UseImplementation then
  626. StartImplementation;
  627. EndSource;
  628. ParseModule;
  629. if UseImplementation then
  630. FDeclarations:=Module.ImplementationSection
  631. else
  632. FDeclarations:=Module.InterfaceSection;
  633. end;
  634. procedure TTestParser.ParseModule;
  635. begin
  636. StartParsing;
  637. FParser.ParseMain(FModule);
  638. AssertNotNull('Module resulted in Module',FModule);
  639. AssertEquals('modulename',ChangeFileExt(FFileName,''),Module.Name);
  640. end;
  641. procedure TTestParser.CheckHint(AHint: TPasMemberHint);
  642. begin
  643. HaveHint(AHint,Definition.Hints);
  644. end;
  645. function TTestParser.AssertExpression(const Msg: String; AExpr: TPasExpr;
  646. aKind: TPasExprKind; AClass: TClass): TPasExpr;
  647. begin
  648. AssertNotNull(AExpr);
  649. AssertEquals(Msg+': Correct expression kind',aKind,AExpr.Kind);
  650. AssertEquals(Msg+': Correct expression class',AClass,AExpr.ClassType);
  651. Result:=AExpr;
  652. end;
  653. function TTestParser.AssertExpression(const Msg: String; AExpr: TPasExpr;
  654. aKind: TPasExprKind; AValue: String): TPrimitiveExpr;
  655. begin
  656. Result:=AssertExpression(Msg,AExpr,aKind,TPrimitiveExpr) as TPrimitiveExpr;
  657. AssertEquals(Msg+': Primitive expression value',AValue,TPrimitiveExpr(AExpr).Value);
  658. end;
  659. procedure TTestParser.AssertExportSymbol(const Msg: String; AIndex: Integer;
  660. AName, AExportName: String; AExportIndex: Integer);
  661. Var
  662. E: TPasExportSymbol;
  663. begin
  664. AssertNotNull(Msg+'Have export symbols list',PasLibrary.LibrarySection.ExportSymbols);
  665. if AIndex>=PasLibrary.LibrarySection.ExportSymbols.Count then
  666. Fail(Format(Msg+'%d not a valid export list symbol',[AIndex]));
  667. AssertNotNull(Msg+'Have export symbol',PasLibrary.LibrarySection.ExportSymbols[Aindex]);
  668. AssertEquals(Msg+'Correct export symbol class',TPasExportSymbol,TObject(PasLibrary.LibrarySection.ExportSymbols[Aindex]).ClassType);
  669. E:=TPasExportSymbol(PasLibrary.LibrarySection.ExportSymbols[Aindex]);
  670. AssertEquals(Msg+'Correct export symbol name',AName,E.Name);
  671. if (AExportName='') then
  672. AssertNull(Msg+'No export name',E.ExportName)
  673. else
  674. begin
  675. AssertNotNull(Msg+'Export name symbol',E.ExportName);
  676. AssertEquals(Msg+'TPrimitiveExpr',TPrimitiveExpr,E.ExportName.CLassType);
  677. AssertEquals(Msg+'Correct export symbol export name ',''''+AExportName+'''',TPrimitiveExpr(E.ExportName).Value);
  678. end;
  679. If AExportIndex=-1 then
  680. AssertNull(Msg+'No export name',E.ExportIndex)
  681. else
  682. begin
  683. AssertNotNull(Msg+'Export name symbol',E.ExportIndex);
  684. AssertEquals(Msg+'TPrimitiveExpr',TPrimitiveExpr,E.ExportIndex.CLassType);
  685. AssertEquals(Msg+'Correct export symbol export index',IntToStr(AExportindex),TPrimitiveExpr(E.ExportIndex).Value);
  686. end;
  687. end;
  688. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  689. AActual: TPasExprKind);
  690. begin
  691. AssertEquals(Msg,GetEnumName(TypeInfo(TPasExprKind),Ord(AExpected)),
  692. GetEnumName(TypeInfo(TPasExprKind),Ord(AActual)));
  693. end;
  694. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  695. AActual: TLoopType);
  696. begin
  697. AssertEquals(Msg,GetEnumName(TypeInfo(TLoopType),Ord(AExpected)),
  698. GetEnumName(TypeInfo(TLoopType),Ord(AActual)));
  699. end;
  700. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  701. AActual: TPasObjKind);
  702. begin
  703. AssertEquals(Msg,GetEnumName(TypeInfo(TPasObjKind),Ord(AExpected)),
  704. GetEnumName(TypeInfo(TPasObjKind),Ord(AActual)));
  705. end;
  706. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  707. AActual: TexprOpcode);
  708. begin
  709. AssertEquals(Msg,GetEnumName(TypeInfo(TexprOpcode),Ord(AExpected)),
  710. GetEnumName(TypeInfo(TexprOpcode),Ord(AActual)));
  711. end;
  712. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  713. AActual: TPasMemberHint);
  714. begin
  715. AssertEquals(Msg,GetEnumName(TypeInfo(TPasMemberHint),Ord(AExpected)),
  716. GetEnumName(TypeInfo(TPasMemberHint),Ord(AActual)));
  717. end;
  718. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  719. AActual: TCallingConvention);
  720. begin
  721. AssertEquals(Msg,GetEnumName(TypeInfo(TCallingConvention),Ord(AExpected)),
  722. GetEnumName(TypeInfo(TCallingConvention),Ord(AActual)));
  723. end;
  724. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  725. AActual: TArgumentAccess);
  726. begin
  727. AssertEquals(Msg,GetEnumName(TypeInfo(TArgumentAccess),Ord(AExpected)),
  728. GetEnumName(TypeInfo(TArgumentAccess),Ord(AActual)));
  729. end;
  730. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  731. AActual: TVariableModifier);
  732. begin
  733. AssertEquals(Msg,GetEnumName(TypeInfo(TVariableModifier),Ord(AExpected)),
  734. GetEnumName(TypeInfo(TVariableModifier),Ord(AActual)));
  735. end;
  736. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  737. AActual: TVariableModifiers);
  738. Function sn (S : TVariableModifiers) : string;
  739. Var
  740. M : TVariableModifier;
  741. begin
  742. Result:='';
  743. For M:=Low(TVariableModifier) to High(TVariableModifier) do
  744. if M in S then
  745. begin
  746. if (Result<>'') then
  747. Result:=Result+',';
  748. end;
  749. Result:='['+Result+']';
  750. end;
  751. begin
  752. AssertEquals(Msg,Sn(AExpected),Sn(AActual));
  753. end;
  754. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  755. AActual: TPasMemberVisibility);
  756. begin
  757. AssertEquals(Msg,GetEnumName(TypeInfo(TPasMemberVisibility),Ord(AExpected)),
  758. GetEnumName(TypeInfo(TPasMemberVisibility),Ord(AActual)));
  759. end;
  760. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  761. AActual: TProcedureModifier);
  762. begin
  763. AssertEquals(Msg,GetEnumName(TypeInfo(TProcedureModifier),Ord(AExpected)),
  764. GetEnumName(TypeInfo(TProcedureModifier),Ord(AActual)));
  765. end;
  766. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  767. AActual: TProcedureModifiers);
  768. Function Sn (S : TProcedureModifiers) : String;
  769. Var
  770. m : TProcedureModifier;
  771. begin
  772. Result:='';
  773. For M:=Low(TProcedureModifier) to High(TProcedureModifier) do
  774. If (m in S) then
  775. begin
  776. If (Result<>'') then
  777. Result:=Result+',';
  778. Result:=Result+GetEnumName(TypeInfo(TProcedureModifier),Ord(m))
  779. end;
  780. end;
  781. begin
  782. AssertEquals(Msg,Sn(AExpected),SN(AActual));
  783. end;
  784. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  785. AActual: TProcTypeModifiers);
  786. Function Sn (S : TProcTypeModifiers) : String;
  787. Var
  788. m : TProcTypeModifier;
  789. begin
  790. Result:='';
  791. For M:=Low(TProcTypeModifier) to High(TProcTypeModifier) do
  792. If (m in S) then
  793. begin
  794. If (Result<>'') then
  795. Result:=Result+',';
  796. Result:=Result+GetEnumName(TypeInfo(TProcTypeModifier),Ord(m))
  797. end;
  798. end;
  799. begin
  800. AssertEquals(Msg,Sn(AExpected),SN(AActual));
  801. end;
  802. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  803. AActual: TAssignKind);
  804. begin
  805. AssertEquals(Msg,GetEnumName(TypeInfo(TAssignKind),Ord(AExpected)),
  806. GetEnumName(TypeInfo(TAssignKind),Ord(AActual)));
  807. end;
  808. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  809. AActual: TProcedureMessageType);
  810. begin
  811. AssertEquals(Msg,GetEnumName(TypeInfo(TProcedureMessageType),Ord(AExpected)),
  812. GetEnumName(TypeInfo(TProcedureMessageType),Ord(AActual)));
  813. end;
  814. procedure TTestParser.AssertEquals(const Msg: String; AExpected,
  815. AActual: TOperatorType);
  816. begin
  817. AssertEquals(Msg,GetEnumName(TypeInfo(TOperatorType),Ord(AExpected)),
  818. GetEnumName(TypeInfo(TOperatorType),Ord(AActual)));
  819. end;
  820. procedure TTestParser.AssertSame(const Msg: String; AExpected,
  821. AActual: TPasElement);
  822. begin
  823. if AExpected=AActual then exit;
  824. AssertEquals(Msg,GetPasElementDesc(AExpected),GetPasElementDesc(AActual));
  825. end;
  826. procedure TTestParser.HaveHint(AHint: TPasMemberHint; AHints: TPasMemberHints);
  827. begin
  828. If not (AHint in AHints) then
  829. Fail(GetEnumName(TypeInfo(TPasMemberHint),Ord(AHint))+'hint expected.');
  830. end;
  831. end.