tcscanner.pp 24 KB

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