tcscanner.pp 24 KB

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