tcscanner.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  1. unit tcscanner;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Typinfo, fpcunit, testregistry, jstoken, jsscanner;
  6. type
  7. { TTestLineReader }
  8. TTestLineReader = Class(TTestCase)
  9. Private
  10. FData: TStringStream;
  11. FReader : TStreamLineReader;
  12. protected
  13. Procedure CreateReader(AInput : String);
  14. procedure TearDown; override;
  15. published
  16. Procedure TestEmpty;
  17. Procedure TestReadLine;
  18. Procedure TestReadLines13;
  19. Procedure TestReadLines10;
  20. Procedure TestReadLines1310;
  21. procedure TestReadLinesEOF13;
  22. procedure TestReadLinesEOF10;
  23. procedure TestReadLinesEOF1310;
  24. procedure TestReadEmptyLines101010;
  25. end;
  26. { TTestJSScanner }
  27. TTestJSScanner = class(TTestCase)
  28. Private
  29. FStream : TStream;
  30. FLineReader : TLineReader;
  31. FScanner : TJSScanner;
  32. FErrorSource : String;
  33. procedure AssertEquals(AMessage: String; AExpected, AActual : TJSToken); overload;
  34. procedure CheckToken(AToken: TJSToken; ASource: String);
  35. procedure CheckTokens(ASource: String; ATokens: array of TJSToken);
  36. procedure DoTestFloat(F: Double);
  37. procedure DoTestFloat(F: Double; S: String);
  38. procedure DoTestString(S: String);
  39. procedure TestErrorSource;
  40. protected
  41. Function CreateScanner(AInput : String) : TJSScanner;
  42. procedure FreeScanner;
  43. procedure SetUp; override;
  44. procedure TearDown; override;
  45. Property Scanner : TJSScanner Read FScanner;
  46. published
  47. Procedure TestEmpty;
  48. procedure TestAndAnd;
  49. procedure TestAndEq;
  50. procedure TestAssign;
  51. procedure TestBraceClose;
  52. procedure TestBraceOpen;
  53. procedure TestColon;
  54. procedure TestComma;
  55. procedure TestCurlyBraceClose;
  56. procedure TestCurlyBraceOpen;
  57. procedure TestDiv;
  58. procedure TestDiveq;
  59. procedure TestXor;
  60. procedure TestXoreq;
  61. procedure TestDot;
  62. procedure TestEq;
  63. procedure TestGE;
  64. procedure TestFalse;
  65. procedure TestInv;
  66. procedure TestNot;
  67. procedure TestString;
  68. procedure TestTrue;
  69. procedure TestGreaterThan;
  70. procedure TestLE;
  71. procedure TestLessThan;
  72. procedure TestLSHIFT;
  73. procedure TestLSHIFTEQ;
  74. procedure TestMinus;
  75. procedure TestMinusEQ;
  76. procedure TestMinusMinus;
  77. procedure TestModeq;
  78. procedure TestMul;
  79. procedure TestNE;
  80. procedure TestNSE;
  81. procedure TestOREQ;
  82. procedure TestOROR;
  83. procedure TestPlus;
  84. procedure TestPlusEq;
  85. procedure TestPlusPlus;
  86. procedure TestRShift;
  87. procedure TestRShiftEq;
  88. procedure TestSemicolon;
  89. procedure TestSEq;
  90. procedure TestSquaredBraceClose;
  91. procedure TestSquaredBraceOpen;
  92. procedure TestStarEq;
  93. procedure TestURShift;
  94. procedure TestURShiftEq;
  95. procedure TestBreak;
  96. procedure TestCase;
  97. procedure TestCatch;
  98. procedure TestContinue;
  99. procedure TestDefault;
  100. procedure TestDelete;
  101. procedure TestDO;
  102. procedure TestElse;
  103. procedure TestFinally;
  104. procedure TestFor;
  105. procedure TestFunction;
  106. procedure TestIf;
  107. procedure TestIn;
  108. procedure TestInstanceOf;
  109. procedure TestNew;
  110. procedure TestReturn;
  111. procedure TestSwitch;
  112. procedure TestThis;
  113. procedure TestThrow;
  114. procedure TestTry;
  115. procedure TestTypeOf;
  116. procedure TestVar;
  117. procedure TestVoid;
  118. procedure TestWhile;
  119. procedure TestWith;
  120. Procedure Test2Words;
  121. procedure Test3Words;
  122. procedure TestIdentifier;
  123. procedure TestIdentifier2;
  124. procedure TestIdentifier3;
  125. procedure TestIdentifier4;
  126. procedure TestIdentifier5;
  127. procedure TestIdentifierDotIdentifier;
  128. procedure TestEOLN;
  129. procedure TestEOLN2;
  130. procedure TestEOLN3;
  131. procedure TestEOLN4;
  132. procedure TestComment1;
  133. procedure TestComment2;
  134. procedure TestComment3;
  135. procedure TestComment4;
  136. procedure TestComment5;
  137. procedure TestComment6;
  138. procedure TestFloat;
  139. procedure TestStringError;
  140. procedure TestFloatError;
  141. end;
  142. implementation
  143. Function TTestJSScanner.CreateScanner(AInput : String) : TJSScanner;
  144. begin
  145. FStream:=TStringStream.Create(AInput);
  146. FLineReader:=TStreamLineReader.Create(Fstream);
  147. FScanner:=TJSScanner.Create(FLineReader);
  148. Result:=FScanner;
  149. end;
  150. procedure TTestJSScanner.FreeScanner;
  151. begin
  152. FreeAndNil(FScanner);
  153. FreeAndNil(FLineReader);
  154. FreeAndNil(FStream);
  155. end;
  156. procedure TTestJSScanner.SetUp;
  157. begin
  158. inherited SetUp;
  159. end;
  160. procedure TTestJSScanner.TestEmpty;
  161. Var
  162. J : TJSToken;
  163. begin
  164. CreateScanner('');
  165. J:=Scanner.FetchToken;
  166. If (J<>tjsEOF) then
  167. Fail('Empty returns EOF');
  168. end;
  169. procedure TTestJSScanner.AssertEquals(AMessage : String; AExpected, AActual: TJSToken);
  170. Var
  171. S,EN1,EN2 : String;
  172. begin
  173. If (AActual<>AExpected) then
  174. begin
  175. EN1:=GetEnumName(TypeINfo(TJSToken),Ord(AExpected));
  176. EN2:=GetEnumName(TypeINfo(TJSToken),Ord(AActual));
  177. S:=Format('%s : %s <> %s',[AMessage,EN1,EN2]);
  178. Fail(S);
  179. end;
  180. end;
  181. procedure TTestJSScanner.CheckToken(AToken : TJSToken; ASource : String);
  182. Var
  183. J : TJSToken;
  184. EN2 : String;
  185. begin
  186. CreateScanner(ASource);
  187. J:=Scanner.FetchToken;
  188. EN2:=GetEnumName(TypeINfo(TJSToken),Ord(AToken));
  189. AssertEquals(Format('Source %s should result in %s.',[ASource,EN2]),AToken,J);
  190. end;
  191. procedure TTestJSScanner.TestAndAnd;
  192. begin
  193. CheckToken(tjsAndAnd,'&&');
  194. end;
  195. procedure TTestJSScanner.TestAndEq;
  196. begin
  197. CheckToken(tjsAndEq,'&=');
  198. end;
  199. procedure TTestJSScanner.TestBraceOpen;
  200. begin
  201. CheckToken(tjsBraceOpen,'(');
  202. end;
  203. procedure TTestJSScanner.TestBraceClose;
  204. begin
  205. CheckToken(tjsBraceClose,')');
  206. end;
  207. procedure TTestJSScanner.TestSquaredBraceClose;
  208. begin
  209. CheckToken(tjsSquaredBraceClose,']');
  210. end;
  211. procedure TTestJSScanner.TestSquaredBraceOpen;
  212. begin
  213. CheckToken(tjssQuaredBraceOpen,'[');
  214. end;
  215. procedure TTestJSScanner.TestCurlyBraceOpen;
  216. begin
  217. CheckToken(tjsCurlyBraceOpen,'{');
  218. end;
  219. procedure TTestJSScanner.TestCurlyBraceClose;
  220. begin
  221. CheckToken(tjsCurlyBraceClose,'}');
  222. end;
  223. procedure TTestJSScanner.TestComma;
  224. begin
  225. CheckToken(tjsComma,',');
  226. end;
  227. procedure TTestJSScanner.TestColon;
  228. begin
  229. CheckToken(tjsColon,':');
  230. end;
  231. procedure TTestJSScanner.TestDot;
  232. begin
  233. CheckToken(tjsDot,'.');
  234. end;
  235. procedure TTestJSScanner.TestSemicolon;
  236. begin
  237. CheckToken(tjsSemicolon,';');
  238. end;
  239. procedure TTestJSScanner.TestAssign;
  240. begin
  241. CheckToken(tjsAssign,'=');
  242. end;
  243. procedure TTestJSScanner.TestGreaterThan;
  244. begin
  245. CheckToken(tjsGT,'>');
  246. end;
  247. procedure TTestJSScanner.TestLessThan;
  248. begin
  249. CheckToken(tjsLT,'<');
  250. end;
  251. procedure TTestJSScanner.TestPlus;
  252. begin
  253. CheckToken(tjsPlus,'+');
  254. end;
  255. procedure TTestJSScanner.TestMinus;
  256. begin
  257. CheckToken(tjsMinus,'-');
  258. end;
  259. procedure TTestJSScanner.TestMul;
  260. begin
  261. CheckToken(tjsMul,'*');
  262. end;
  263. procedure TTestJSScanner.TestDiv;
  264. begin
  265. CheckToken(tjsDiv,'/');
  266. end;
  267. procedure TTestJSScanner.TestEq;
  268. begin
  269. CheckToken(tjsEq,'==');
  270. end;
  271. procedure TTestJSScanner.TestGE;
  272. begin
  273. CheckToken(tjsGE,'>=');
  274. end;
  275. procedure TTestJSScanner.TestLE;
  276. begin
  277. CheckToken(tjsLE,'<=');
  278. end;
  279. procedure TTestJSScanner.TestLSHIFT;
  280. begin
  281. CheckToken(tjsLShift,'<<');
  282. end;
  283. procedure TTestJSScanner.TestLSHIFTEQ;
  284. begin
  285. CheckToken(tjsLShiftEq,'<<=');
  286. end;
  287. procedure TTestJSScanner.TestMinusEQ;
  288. begin
  289. CheckToken(tjsMinusEq,'-=');
  290. end;
  291. procedure TTestJSScanner.TestMinusMinus;
  292. begin
  293. CheckToken(tjsMinusMinus,'--');
  294. end;
  295. procedure TTestJSScanner.TestModeq;
  296. begin
  297. CheckToken(tjsModeq,'%=');
  298. end;
  299. procedure TTestJSScanner.TestDiveq;
  300. begin
  301. CheckToken(tjsDiveq,'/=');
  302. end;
  303. procedure TTestJSScanner.TestXor;
  304. begin
  305. CheckToken(tjsXOR,'^');
  306. end;
  307. procedure TTestJSScanner.TestXoreq;
  308. begin
  309. CheckToken(tjsXOREQ,'^=');
  310. end;
  311. procedure TTestJSScanner.TestNE;
  312. begin
  313. CheckToken(tjsNE,'!=');
  314. end;
  315. procedure TTestJSScanner.TestInv;
  316. begin
  317. CheckToken(tjsInv,'~');
  318. end;
  319. procedure TTestJSScanner.TestNot;
  320. begin
  321. CheckToken(tjsNot,'!');
  322. end;
  323. procedure TTestJSScanner.TestTrue;
  324. begin
  325. CheckToken(tjsTrue,'true');
  326. end;
  327. procedure TTestJSScanner.TestFalse;
  328. begin
  329. CheckToken(tjsFalse,'false');
  330. end;
  331. procedure TTestJSScanner.TestOREQ;
  332. begin
  333. CheckToken(tjsOREQ,'|=');
  334. end;
  335. procedure TTestJSScanner.TestOROR;
  336. begin
  337. CheckToken(tjsOROR,'||');
  338. end;
  339. procedure TTestJSScanner.TestPlusEq;
  340. begin
  341. CheckToken(tjsPlusEq,'+=');
  342. end;
  343. procedure TTestJSScanner.TestPlusPlus;
  344. begin
  345. CheckToken(tjsPlusPlus,'++');
  346. end;
  347. procedure TTestJSScanner.TestURShift;
  348. begin
  349. CheckToken(tjsURSHIFT,'>>>');
  350. end;
  351. procedure TTestJSScanner.TestURShiftEq;
  352. begin
  353. CheckToken(tjsURSHIFTEQ,'>>>=');
  354. end;
  355. procedure TTestJSScanner.TestRShift;
  356. begin
  357. CheckToken(tjsRSHIFT,'>>');
  358. end;
  359. procedure TTestJSScanner.TestRShiftEq;
  360. begin
  361. CheckToken(tjsRSHIFTEQ,'>>=');
  362. end;
  363. procedure TTestJSScanner.TestSEq;
  364. begin
  365. CheckToken(tjsSEQ,'===');
  366. end;
  367. procedure TTestJSScanner.TestNSE;
  368. begin
  369. CheckToken(tjsSNE,'!==');
  370. end;
  371. procedure TTestJSScanner.TestStarEq;
  372. begin
  373. CheckToken(tjsMulEq,'*=');
  374. end;
  375. procedure TTestJSScanner.TestBreak;
  376. begin
  377. CheckToken(tjsBreak,'break');
  378. end;
  379. procedure TTestJSScanner.TestCase;
  380. begin
  381. CheckToken(tjscase,'case');
  382. end;
  383. procedure TTestJSScanner.TestCatch;
  384. begin
  385. CheckToken(tjscatch,'catch');
  386. end;
  387. procedure TTestJSScanner.TestContinue;
  388. begin
  389. CheckToken(tjscontinue,'continue');
  390. end;
  391. procedure TTestJSScanner.TestDefault;
  392. begin
  393. CheckToken(tjsdefault,'default');
  394. end;
  395. procedure TTestJSScanner.TestDelete;
  396. begin
  397. CheckToken(tjsdelete,'delete');
  398. end;
  399. procedure TTestJSScanner.TestDO;
  400. begin
  401. CheckToken(tjsdo,'do');
  402. end;
  403. procedure TTestJSScanner.TestElse;
  404. begin
  405. CheckToken(tjselse,'else');
  406. end;
  407. procedure TTestJSScanner.TestFinally;
  408. begin
  409. CheckToken(tjsfinally,'finally');
  410. end;
  411. procedure TTestJSScanner.TestFor;
  412. begin
  413. CheckToken(tjsfor,'for');
  414. end;
  415. procedure TTestJSScanner.TestFunction;
  416. begin
  417. CheckToken(tjsfunction,'function');
  418. end;
  419. procedure TTestJSScanner.TestIf;
  420. begin
  421. CheckToken(tjsif,'if');
  422. end;
  423. procedure TTestJSScanner.TestIn;
  424. begin
  425. CheckToken(tjsin,'in');
  426. end;
  427. procedure TTestJSScanner.TestInstanceOf;
  428. begin
  429. CheckToken(tjsinstanceof,'instanceof');
  430. end;
  431. procedure TTestJSScanner.TestNew;
  432. begin
  433. CheckToken(tjsnew,'new');
  434. end;
  435. procedure TTestJSScanner.TestReturn;
  436. begin
  437. CheckToken(tjsreturn,'return');
  438. end;
  439. procedure TTestJSScanner.TestSwitch;
  440. begin
  441. CheckToken(tjsswitch,'switch');
  442. end;
  443. procedure TTestJSScanner.TestThis;
  444. begin
  445. CheckToken(tjsThis,'this');
  446. end;
  447. procedure TTestJSScanner.TestThrow;
  448. begin
  449. CheckToken(tjsThrow,'throw');
  450. end;
  451. procedure TTestJSScanner.TestTry;
  452. begin
  453. CheckToken(tjsTry,'try');
  454. end;
  455. procedure TTestJSScanner.TestTypeOf;
  456. begin
  457. CheckToken(tjstypeof,'typeof');
  458. end;
  459. procedure TTestJSScanner.TestVar;
  460. begin
  461. CheckToken(tjsvar,'var');
  462. end;
  463. procedure TTestJSScanner.TestVoid;
  464. begin
  465. CheckToken(tjsvoid,'void');
  466. end;
  467. procedure TTestJSScanner.TestWhile;
  468. begin
  469. CheckToken(tjswhile,'while');
  470. end;
  471. procedure TTestJSScanner.TestWith;
  472. begin
  473. CheckToken(tjswith,'with');
  474. end;
  475. procedure TTestJSScanner.CheckTokens(ASource : String; ATokens : Array of TJSToken);
  476. Var
  477. I : Integer;
  478. J : TJSToken;
  479. S : String;
  480. begin
  481. CreateScanner(ASource);
  482. For I:=Low(ATokens) to High(ATokens) do
  483. begin
  484. J:=FScanner.FetchToken;
  485. S:=GetEnumName(TypeINfo(TJSToken),Ord(ATokens[i]));
  486. S:=Format('Source "%s", token %d (%s): expected %s',[ASource,I,FScanner.CurTokenString,S]);
  487. AssertEquals(S,ATokens[i],J);
  488. end;
  489. end;
  490. procedure TTestJSScanner.Test2Words;
  491. begin
  492. CheckTokens('with do',[tjsWith,tjsDo]);
  493. end;
  494. procedure TTestJSScanner.Test3Words;
  495. begin
  496. CheckTokens('with do for',[tjsWith,tjsDo,tjsFor]);
  497. end;
  498. procedure TTestJSScanner.TestIdentifier;
  499. begin
  500. CheckToken(tjsIdentifier,'something');
  501. AssertEquals('Correct identifier','something',FScanner.CurTokenString);
  502. end;
  503. procedure TTestJSScanner.TestIdentifier2;
  504. begin
  505. CheckToken(tjsIdentifier,'_something');
  506. AssertEquals('Correct identifier','_something',FScanner.CurTokenString);
  507. end;
  508. procedure TTestJSScanner.TestIdentifier3;
  509. begin
  510. CheckToken(tjsIdentifier,'$');
  511. AssertEquals('Correct identifier','$',FScanner.CurTokenString);
  512. end;
  513. procedure TTestJSScanner.TestIdentifier4;
  514. begin
  515. CheckToken(tjsIdentifier,'_0');
  516. AssertEquals('Correct identifier','_0',FScanner.CurTokenString);
  517. end;
  518. procedure TTestJSScanner.TestIdentifier5;
  519. begin
  520. CheckToken(tjsIdentifier,'$0');
  521. AssertEquals('Correct identifier','$0',FScanner.CurTokenString);
  522. end;
  523. procedure TTestJSScanner.TestIdentifierDotIdentifier;
  524. begin
  525. CheckTokens('something.different',[tjsIdentifier,tjsdot,tjsIdentifier]);
  526. // AssertEquals('Correct identifier','something',FScanner.CurTokenString);
  527. end;
  528. procedure TTestJSScanner.TestEOLN;
  529. begin
  530. CreateScanner('something');
  531. FScanner.FetchToken;
  532. AssertEquals('Got to end of line after reading single token at EOF',True,FScanner.IsEndOfLine);
  533. // AssertEquals('Correct identifier','something',FScanner.CurTokenString);
  534. end;
  535. procedure TTestJSScanner.TestEOLN2;
  536. begin
  537. CreateScanner('something different');
  538. FScanner.FetchToken;
  539. AssertEquals('Not yet end of line after reading single token at EOF',False,FScanner.IsEndOfLine);
  540. end;
  541. procedure TTestJSScanner.TestEOLN3;
  542. begin
  543. CreateScanner('something'#13#10'different');
  544. FScanner.FetchToken;
  545. AssertEquals('End of line after reading single token',True,FScanner.IsEndOfLine);
  546. end;
  547. procedure TTestJSScanner.TestEOLN4;
  548. begin
  549. CreateScanner('something'#10'different');
  550. FScanner.FetchToken;
  551. AssertEquals('End of line after reading first token',True,FScanner.IsEndOfLine);
  552. FScanner.FetchToken;
  553. AssertEquals('End of line after reading second token',True,FScanner.IsEndOfLine);
  554. end;
  555. procedure TTestJSScanner.TestComment1;
  556. begin
  557. CreateScanner('// some comment string');
  558. AssertEquals('Comment line is skipped',tjsEOF,FScanner.FetchToken);
  559. end;
  560. procedure TTestJSScanner.TestComment2;
  561. begin
  562. CreateScanner('// some comment string');
  563. FScanner.ReturnComments:=True;
  564. AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken);
  565. AssertEquals('Comment contents is returned',' some comment string',FScanner.CurTokenString);
  566. end;
  567. procedure TTestJSScanner.TestComment3;
  568. begin
  569. CreateScanner('/* some comment string */');
  570. AssertEquals('Comment line is skipped',tjsEOF,FScanner.FetchToken);
  571. end;
  572. procedure TTestJSScanner.TestComment4;
  573. begin
  574. CreateScanner('/* some comment string */');
  575. FScanner.ReturnComments:=True;
  576. AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken);
  577. AssertEquals('Comment contents is returned',' some comment string ',FScanner.CurTokenString);
  578. end;
  579. procedure TTestJSScanner.TestComment5;
  580. begin
  581. CreateScanner('/* some nested comment // string */');
  582. FScanner.ReturnComments:=True;
  583. AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken);
  584. AssertEquals('Comment contents is returned',' some nested comment // string ',FScanner.CurTokenString);
  585. end;
  586. procedure TTestJSScanner.TestComment6;
  587. begin
  588. CreateScanner('// /* some nested comment string */');
  589. FScanner.ReturnComments:=True;
  590. AssertEquals('Comment line is returned',tjsComment,FScanner.FetchToken);
  591. AssertEquals('Comment contents is returned',' /* some nested comment string */',FScanner.CurTokenString);
  592. end;
  593. procedure TTestJSScanner.TearDown;
  594. begin
  595. FreeScanner;
  596. Inherited;
  597. end;
  598. procedure TTestJSScanner.DoTestFloat(F : Double);
  599. Var
  600. S : String;
  601. begin
  602. Str(F,S);
  603. DoTestFloat(F,S);
  604. end;
  605. procedure TTestJSScanner.DoTestFloat(F : Double; S : String);
  606. Var
  607. J : TJSToken;
  608. C : Double;
  609. I : integer;
  610. V : String;
  611. begin
  612. CreateScanner(S);
  613. try
  614. J:=FScanner.FetchToken;
  615. AssertEquals(S+' is a number',tjsNumber,J);
  616. V:=FScanner.CurTokenString;
  617. If (Copy(V,1,2)='0x') then
  618. begin
  619. Flush(output);
  620. V:='$'+Copy(V,3,Length(V)-2);
  621. C:=StrToInt(V);
  622. end
  623. else
  624. begin
  625. Val(V,C,I);
  626. If (I<>0) then
  627. Fail(FScanner.CurTokenString+' does not contain a float value');
  628. end;
  629. AssertEquals('Parsed float equals original float',F,C);
  630. finally
  631. FreeScanner;
  632. end;
  633. end;
  634. procedure TTestJSScanner.TestFloat;
  635. begin
  636. DoTestFloat(1.2);
  637. DoTestFloat(-1.2);
  638. DoTestFloat(0);
  639. DoTestFloat(1.2e1);
  640. DoTestFloat(-1.2e1);
  641. DoTestFloat(0);
  642. DoTestFloat(1.2,'1.2');
  643. DoTestFloat(-1.2,'-1.2');
  644. DoTestFloat(0,'0.0');
  645. DoTestFloat(255,'0xff')
  646. end;
  647. procedure TTestJSScanner.TestFloatError;
  648. begin
  649. FErrorSource:='1xz';
  650. AssertException('Wrong float',EJSScannerError,@TestErrorSource);
  651. end;
  652. procedure TTestJSScanner.DoTestString(S: String);
  653. Var
  654. J : TJSToken;
  655. begin
  656. CreateScanner(S);
  657. try
  658. J:=FScanner.FetchToken;
  659. AssertEquals(S+' is a string',tjsString,J);
  660. If (Length(S)>0) and (S[1] in ['"','''']) then
  661. S:=Copy(S,2,Length(S)-2);
  662. AssertEquals('Correct string is returned',S,FScanner.CurTokenString);
  663. finally
  664. FreeScanner;
  665. end;
  666. end;
  667. procedure TTestJSScanner.TestString;
  668. begin
  669. DoTestString('"A string"');
  670. DoTestString('""');
  671. DoTestString('''''');
  672. DoTestString('''A string''');
  673. end;
  674. procedure TTestJSScanner.TestErrorSource;
  675. begin
  676. CreateScanner(FErrorSource);
  677. try
  678. While (FScanner.FetchToken<>tjsEOF) do ;
  679. finally
  680. FreeScanner;
  681. end;
  682. end;
  683. procedure TTestJSScanner.TestStringError;
  684. begin
  685. FErrorSource:='"A string';
  686. AssertException('Unterminated string',EJSScannerError,@TestErrorSource);
  687. FErrorSource:='''A string';
  688. AssertException('Unterminated string',EJSScannerError,@TestErrorSource);
  689. end;
  690. { TTestLineReader }
  691. procedure TTestLineReader.CreateReader(AInput: String);
  692. begin
  693. FData:=TStringStream.Create(AInput);
  694. FReader:=TStreamLineReader.Create(FData);
  695. end;
  696. procedure TTestLineReader.TearDown;
  697. begin
  698. FreeAndNil(FReader);
  699. FreeAndNil(FData);
  700. end;
  701. procedure TTestLineReader.TestEmpty;
  702. begin
  703. CreateReader('');
  704. AssertEquals('Empty reader returns EOF',True,FReader.IsEOF);
  705. AssertEquals('Empty reader returns empty string','',FReader.ReadLine);
  706. end;
  707. procedure TTestLineReader.TestReadLine;
  708. begin
  709. CreateReader('Something');
  710. AssertEquals('Reader with 1 line returns 1 line','Something',FReader.ReadLine);
  711. AssertEquals('EOF true after reading line',True,FReader.IsEOF);
  712. end;
  713. procedure TTestLineReader.TestReadLines13;
  714. begin
  715. CreateReader('Something'#13'else');
  716. AssertEquals('Reader with 2 lines returns 1st line','Something',FReader.ReadLine);
  717. AssertEquals('Reader with 2 lines returns 2nd line','else',FReader.ReadLine);
  718. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  719. end;
  720. procedure TTestLineReader.TestReadLines10;
  721. begin
  722. CreateReader('Something'#10'else');
  723. AssertEquals('Reader with 2 lines returns 1st line','Something',FReader.ReadLine);
  724. AssertEquals('Reader with 2 lines returns 2nd line','else',FReader.ReadLine);
  725. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  726. end;
  727. procedure TTestLineReader.TestReadLines1310;
  728. begin
  729. CreateReader('Something'#13#10'else');
  730. AssertEquals('Reader with 2 lines returns 1st line','Something',FReader.ReadLine);
  731. AssertEquals('Reader with 2 lines returns 2nd line','else',FReader.ReadLine);
  732. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  733. end;
  734. procedure TTestLineReader.TestReadLinesEOF13;
  735. begin
  736. CreateReader('Something'#13);
  737. AssertEquals('Reader with 2 lines + CR returns 1st line','Something',FReader.ReadLine);
  738. AssertEquals('Reader with 1 lines + CR returns empty 2nd line','',FReader.ReadLine);
  739. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  740. end;
  741. procedure TTestLineReader.TestReadLinesEOF10;
  742. begin
  743. CreateReader('Something'#10);
  744. AssertEquals('Reader with 2 lines + LF returns 1st line','Something',FReader.ReadLine);
  745. AssertEquals('Reader with 1 lines + LF returns empty 2nd line','',FReader.ReadLine);
  746. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  747. end;
  748. procedure TTestLineReader.TestReadLinesEOF1310;
  749. begin
  750. CreateReader('Something'#13#10);
  751. AssertEquals('Reader with 2 lines + CRLF returns 1st line','Something',FReader.ReadLine);
  752. AssertEquals('Reader with 1 lines + CRLF returns empty 2nd line','',FReader.ReadLine);
  753. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  754. end;
  755. procedure TTestLineReader.TestReadEmptyLines101010;
  756. begin
  757. CreateReader('Something'#10#10#10);
  758. AssertEquals('Reader with 1 line + LFLFLF returns 1st line','Something',FReader.ReadLine);
  759. AssertEquals('EOF false after reading line 1',False,FReader.IsEOF);
  760. AssertEquals('Reader with 1 line + LFLFLF returns empty 2nd line','',FReader.ReadLine);
  761. AssertEquals('EOF false after reading line 2',False,FReader.IsEOF);
  762. AssertEquals('Reader with 1 line + LFLFLF returns empty 3nd line','',FReader.ReadLine);
  763. AssertEquals('EOF true after reading lines',True,FReader.IsEOF);
  764. end;
  765. initialization
  766. RegisterTests([TTestLineReader,TTestJSScanner]);
  767. end.