parsefiles.pas 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. { *********************************************************************
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2021 Michael Van Canneyt.
  4. Javascript & typescript parser demo
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. program parsefiles;
  12. {$mode objfpc}{$H+}
  13. uses
  14. Classes, SysUtils, CustApp, Math, jsTree, jsScanner, jsParser;
  15. type
  16. TCounts = Record
  17. Total,OK,Failed : Integer;
  18. Stop : Boolean;
  19. end;
  20. { TParseTSApplication }
  21. TParseTSApplication = class(TCustomApplication)
  22. private
  23. FTypescript : Boolean;
  24. FStopOnError : Boolean;
  25. function ParseFile(const aFileName: string): Boolean;
  26. function ParseFiles(const aDirectory: string; RecurseLevel : Integer): TCounts;
  27. protected
  28. procedure DoRun; override;
  29. public
  30. constructor Create(TheOwner: TComponent); override;
  31. destructor Destroy; override;
  32. procedure Usage(Msg : string); virtual;
  33. end;
  34. { TParseTSApplication }
  35. procedure TParseTSApplication.DoRun;
  36. var
  37. ErrorMsg: String;
  38. Directory : String;
  39. Counts : TCounts;
  40. begin
  41. Terminate;
  42. ErrorMsg:=CheckOptions('hd:srt', ['help','directory','stop-on-error','recurse','typescript']);
  43. if (ErrorMsg<>'') or HasOption('h','help') then
  44. begin
  45. Usage(ErrorMsg);
  46. Exit;
  47. end;
  48. FTypescript:=HasOption('t','typescript');
  49. Directory:=GetOptionValue('d','directory');
  50. FStopOnError:=HasOption('s','stop-on-error');
  51. If Directory='' then
  52. Directory:=GetCurrentDir;
  53. Counts:=ParseFiles(Directory,Ord(HasOption('r','recurse')));
  54. With Counts do
  55. Writeln('Statistics: ',Total,' Total, ',OK,' OK, ',Failed, ' Failed');
  56. end;
  57. Function TParseTSApplication.ParseFile(const aFileName : string) : Boolean;
  58. Var
  59. aFile : TStrings;
  60. P : TJSParser;
  61. S : TStringStream;
  62. el : TJSElement;
  63. I : Integer;
  64. EP : EJSParser;
  65. Prefix : String;
  66. begin
  67. Result:=False;
  68. Writeln('Parsing: ',aFileName);
  69. Flush(output);
  70. el:=nil;
  71. S:=Nil;
  72. aFile:=TStringList.Create;
  73. try
  74. aFile.LoadFromFile(aFileName);
  75. S:=TStringStream.Create('');
  76. S.LoadFromFile(aFileName);
  77. P:=TJSParser.Create(S,ecma2021,FTypescript,aFileName);
  78. try
  79. El:=P.Parse;
  80. Result:=True;
  81. except
  82. On E : Exception do
  83. begin
  84. writeln('Error ',E.ClassName,' parsing file ',aFileName,' : ',E.Message);
  85. if E is EJSParser then
  86. begin
  87. Writeln('Offending lines : ');
  88. EP:=EJSParser(E);
  89. For I:=Max(1,EP.ErrorRow-1) to Min(aFile.Count,EP.ErrorRow+1) do
  90. begin
  91. Prefix:=IntToStr(I);
  92. Writeln(Prefix,' : ',aFile[I-1]);
  93. if I=EP.ErrorRow then
  94. Writeln(StringOfChar(' ',EP.ErrorCol-1),StringOfChar('-',Length(Prefix)+3),'^');
  95. end;
  96. end;
  97. end;
  98. end;
  99. finally
  100. el.Free;
  101. aFile.Free;
  102. S.Free;
  103. end;
  104. end;
  105. Function TParseTSApplication.ParseFiles(Const aDirectory : string; RecurseLevel : Integer) : TCounts;
  106. Var
  107. Info : TSearchRec;
  108. Res: TCounts;
  109. Ext : string;
  110. begin
  111. Result:=Default(TCounts);
  112. if FTypeScript then
  113. Ext:='*.d.ts'
  114. else
  115. Ext:='*.js';
  116. If FindFirst(aDirectory+Ext,0,Info)=0 then
  117. try
  118. Repeat
  119. Inc(Result.Total);
  120. if ParseFile(aDirectory+Info.Name) then
  121. Inc(Result.OK)
  122. else
  123. begin
  124. Inc(Result.Failed);
  125. if FStopOnError then
  126. Result.Stop:=True;
  127. end;
  128. until (FindNext(Info)<>0) or Result.Stop;
  129. Finally
  130. FindClose(Info)
  131. end;
  132. if RecurseLevel=0 then
  133. exit;
  134. If FindFirst(aDirectory+'*',faDirectory,Info)=0 then
  135. try
  136. Repeat
  137. if (Info.Attr and faDirectory)=faDirectory then
  138. begin
  139. Res:=ParseFiles(aDirectory+Info.Name+PathDelim,RecurseLevel-1);
  140. Result.Total:=Result.Total+Res.Total;
  141. Result.OK:=Result.OK+Res.OK;
  142. Result.Failed:=Result.Failed+Res.Failed;
  143. Result.Stop:=Result.Stop or Res.Stop
  144. end
  145. until (FindNext(Info)<>0) or Res.Stop;
  146. Finally
  147. FindClose(Info)
  148. end;
  149. end;
  150. constructor TParseTSApplication.Create(TheOwner: TComponent);
  151. begin
  152. inherited Create(TheOwner);
  153. StopOnException:=True;
  154. end;
  155. destructor TParseTSApplication.Destroy;
  156. begin
  157. inherited Destroy;
  158. end;
  159. procedure TParseTSApplication.Usage(Msg: string);
  160. begin
  161. if Msg<>'' then
  162. Writeln('Error : ',Msg);
  163. writeln('Usage: ', ExeName, ' [options]');
  164. Writeln('Where options is one or mote of:');
  165. Writeln('-h --help Display this help text');
  166. Writeln('-d --directory Parse all files in directory');
  167. Writeln('-s --stop-on-error Stop parsing files after an error');
  168. Writeln('-t --typescript Assume typscript');
  169. end;
  170. var
  171. Application: TParseTSApplication;
  172. begin
  173. Application:=TParseTSApplication.Create(nil);
  174. Application.Title:='My Application';
  175. Application.Run;
  176. Application.Free;
  177. end.