webidlparser.pp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903
  1. {
  2. This file is part of the Free Component Library
  3. WEBIDL source parser
  4. Copyright (c) 2021 by Michael Van Canneyt [email protected]
  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. unit webidlparser;
  12. {$mode objfpc}{$H+}
  13. {$WARN 6060 off : }
  14. interface
  15. uses
  16. Classes, SysUtils, Contnrs, webidlscanner, webidldefs;
  17. Type
  18. EWebIDLParser = Class(Exception);
  19. { TWebIDLContext }
  20. TWebIDLVersion = webidlscanner.TWebIDLVersion;
  21. TWebIDLContext = Class (TIDLBaseObject)
  22. private
  23. FAliases: TStrings;
  24. FDefinitions: TIDLDefinitionList;
  25. FHash : TFPObjectHashTable;
  26. Protected
  27. function FindDictionary(aName: UTF8String): TIDLDictionaryDefinition; virtual;
  28. function FindInterface(aName: UTF8String): TIDLInterfaceDefinition; virtual;
  29. procedure AppendDictionaryPartials; virtual;
  30. procedure AppendInterfacePartials; virtual;
  31. procedure AppendInterfaceIncludes; virtual;
  32. procedure ResolveParentTypes; virtual;
  33. Public
  34. Constructor Create(OwnsDefinitions : Boolean = True);
  35. Destructor Destroy; override;
  36. Procedure AppendPartials; virtual;
  37. Procedure AppendIncludes; virtual;
  38. Function GetInterfacesTopologically: TIDLDefinitionList; virtual;
  39. Procedure ResolveTypes; virtual;
  40. function GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean = false): string; virtual;
  41. function IndexOfDefinition(const AName: String): Integer;
  42. Function FindDefinition(const AName : String) : TIDLDefinition;
  43. Function AsString(Full: Boolean): UTF8String; override;
  44. Function Add(aClass : TIDLDefinitionClass; const AName : UTF8String; const aFile: string; aLine, aCol: integer) : TIDLDefinition; override;
  45. Function Add(aParent : TIDLBaseObject; aClass : TIDLDefinitionClass; const AName : UTF8String; const aFile: string; aLine, aCol: integer) : TIDLDefinition; virtual;
  46. Property Definitions : TIDLDefinitionList Read FDefinitions;
  47. Property Aliases : TStrings Read FAliases Write FAliases;
  48. end;
  49. { TWebIDLParser }
  50. TWebIDLParser = Class
  51. private
  52. FContext: TWebIDLContext;
  53. FScanner: TWebIDLScanner;
  54. FOwnsScanner : Boolean;
  55. FVersion: TWebIDLVersion;
  56. procedure SetVersion(AValue: TWebIDLVersion);
  57. Protected
  58. function GetErrorPos: String; virtual;
  59. // Error mechanism
  60. Procedure Error(Msg : String);
  61. Procedure Error(Fmt : String; Args : Array of const);
  62. // Scanner access. Only use this, do not use scanner directly.
  63. function CurrentToken: TIDLToken; virtual;
  64. function GetToken: TIDLToken; virtual;
  65. function CurrentTokenString: UTF8String;
  66. function CurrentRow: integer; virtual;
  67. function CurrentColumn: integer; virtual;
  68. function CurrentFile: string; virtual;
  69. // Get next token, see if it is valid. Raise exception if not.
  70. procedure MaybeFree(Result: TIDLDefinition; aParent: TIDLBaseObject);
  71. Procedure CheckCurrentToken(aToken: TIDLToken);
  72. Procedure CheckCurrentTokens(aTokens: TIDLTokens);
  73. function ExpectToken(aToken: TIDLToken): TIDLToken;
  74. function ExpectTokens(aTokens: TIDLTokens): TIDLToken;
  75. // Extended Attributes
  76. function ParseExtAttributes: TExtAttributeList;
  77. procedure ParseExtAttributes(aList: TExtAttributeList; aTerminator: TIDLToken; ForSerializer: Boolean=False); virtual;
  78. // Definitions
  79. // Type is a type without name of the type
  80. function AddDefinition(aParent : TIDLBaseObject; aClass : TIDLDefinitionClass; const AName : UTF8String) : TIDLDefinition; virtual;
  81. function ParseAttribute(aParent: TIDLBaseObject): TIDLAttributeDefinition; virtual;
  82. function ParseArgument(aParent: TIDLBaseObject): TIDLArgumentDefinition; virtual;
  83. procedure ParseArguments(aParent: TIDLBaseObject);virtual;
  84. function ParseFunction(aParent: TIDLBaseObject): TIDLFunctionDefinition; virtual;
  85. function ParseType(aParent: TIDLBaseObject; FetchFirst: Boolean=True; AllowExtraTypes : Boolean = False): TIDLTypeDefDefinition; virtual;
  86. function ParseDictionaryMember(aParent: TIDLBaseObject): TIDLDictionaryMemberDefinition; virtual;
  87. function CompleteSimpleType(tk: TIDLToken; Var S: UTF8String; out IsNull: Boolean): TIDLToken; virtual;
  88. function ParseMapLikeMember(aParent: TIDLBaseObject): TIDLMaplikeDefinition; virtual;
  89. function ParseSetLikeMember(aParent: TIDLBaseObject): TIDLSetlikeDefinition; virtual;
  90. function ParseRecordTypeDef(aParent: TIDLBaseObject): TIDLRecordDefinition; virtual;
  91. function ParsePromiseTypeDef(aParent: TIDLBaseObject): TIDLPromiseTypeDefDefinition; virtual;
  92. function ParseSequenceTypeDef(aParent : TIDLBaseObject): TIDLSequenceTypeDefDefinition; virtual;
  93. function ParseUnionTypeDef(aParent : TIDLBaseObject): TIDLUnionTypeDefDefinition; virtual;
  94. function ParseConstValue(out aValue: UTF8String; aExtended: Boolean): TConstType; virtual;
  95. function ParseConst(aParent: TIDLBaseObject ): TIDLConstDefinition; virtual;
  96. function ParseCallBack(aParent : TIDLBaseObject): TIDLDefinition; virtual;
  97. function ParseStringifier(aParent : TIDLBaseObject): TIDLDefinition; virtual;
  98. function ParseOperation(aParent: TIDLBaseObject): TIDLFunctionDefinition; virtual;
  99. function ParseSerializer(aParent: TIDLBaseObject): TIDLSerializerDefinition; virtual;
  100. function ParseStatic(aParent: TIDLBaseObject): TIDLDefinition;virtual;
  101. function ParseIterable(aParent : TIDLBaseObject): TIDLIterableDefinition; virtual;
  102. function ParseInterface(aParent : TIDLBaseObject): TIDLInterfaceDefinition; virtual;
  103. function ParseDictionary(aParent : TIDLBaseObject; AllowInheritance : Boolean = True): TIDLDictionaryDefinition; virtual;
  104. function ParseEnum(aParent : TIDLBaseObject): TIDLEnumDefinition; virtual;
  105. function ParseTypeDef(aParent : TIDLBaseObject): TIDLTypeDefDefinition; virtual;
  106. function ParsePartial(aParent : TIDLBaseObject): TIDLStructuredDefinition; virtual;
  107. function ParseImplementsOrIncludes(aParent: TIDLBaseObject): TIDLImplementsOrIncludesDefinition; virtual;
  108. function ParseImplements(Const aName : UTF8String; aParent : TIDLBaseObject): TIDLImplementsDefinition; virtual;
  109. function ParseIncludes(Const aName : UTF8String; aParent : TIDLBaseObject): TIDLIncludesDefinition; virtual;
  110. function ParseDefinition(aParent : TIDLBaseObject): TIDLDefinition; virtual;
  111. procedure ParseDefinitions(aParent : TIDLBaseObject); virtual;
  112. Public
  113. Constructor Create(aContext : TWEBIDLContext; aScanner : TWebIDLScanner); overload;
  114. Constructor Create(aContext : TWEBIDLContext; aSource : UTF8String);overload;
  115. Destructor Destroy; override;
  116. Procedure Parse;
  117. Property Scanner : TWebIDLScanner Read FScanner;
  118. Property Context : TWebIDLContext Read FContext;
  119. Property Version : TWebIDLVersion Read FVersion Write SetVersion;
  120. end;
  121. procedure MergeSort(List: TFPList; const OnCompare: TListSortCompare); overload;
  122. procedure MergeSort(List: TFPList; StartIndex, EndIndex: integer; const OnCompare: TListSortCompare); overload;
  123. implementation
  124. Resourcestring
  125. SErrInvalidToken = 'Invalid token: expected "%s", got: "%s"';
  126. SErrInvalidTokenList = 'Invalid token: expected one of "%s", got: "%s"';
  127. // SExpectedOther = 'Unexpected token in attribute list: "%s".';
  128. SErrUnExpectedToken = 'Unexpected token : "%s"';
  129. SErrTypeNotAllowed = 'Type "%s" not allowed in "%s" type.';
  130. SErrDictionaryNotFound = 'Dictionary %s not found';
  131. SErrInterfaceNotFound = 'Interface %s not found';
  132. SErrInterfaceNotFoundfor = 'Included Interface %s not found for %s';
  133. procedure MergeSort(List: TFPList; const OnCompare: TListSortCompare);
  134. begin
  135. if List=nil then exit;
  136. MergeSort(List,0,List.Count-1,OnCompare);
  137. end;
  138. procedure MergeSort(List: TFPList; StartIndex, EndIndex: integer;
  139. const OnCompare: TListSortCompare);
  140. // sort so that for each i is OnCompare(List[i],List[i+1])<=0
  141. var
  142. MergeList: PPointer;
  143. procedure SmallSort(StartPos, EndPos: PtrInt);
  144. // use insertion sort for small lists
  145. var
  146. i: PtrInt;
  147. Best: PtrInt;
  148. j: PtrInt;
  149. Item: Pointer;
  150. begin
  151. for i:=StartPos to EndPos-1 do begin
  152. Best:=i;
  153. for j:=i+1 to EndPos do
  154. if OnCompare(List[Best],List[j])>0 then
  155. Best:=j;
  156. if Best>i then begin
  157. Item:=List[i];
  158. List[i]:=List[Best];
  159. List[Best]:=Item;
  160. end;
  161. end;
  162. end;
  163. procedure Merge(Pos1, Pos2, Pos3: PtrInt);
  164. // merge two sorted arrays
  165. // the first array ranges Pos1..Pos2-1, the second ranges Pos2..Pos3
  166. var Src1Pos,Src2Pos,DestPos,cmp,a:PtrInt;
  167. begin
  168. while (Pos3>=Pos2) and (OnCompare(List[Pos2-1],List[Pos3])<=0) do
  169. dec(Pos3);
  170. if (Pos1>=Pos2) or (Pos2>Pos3) then exit;
  171. Src1Pos:=Pos2-1;
  172. Src2Pos:=Pos3;
  173. DestPos:=Pos3;
  174. while (Src2Pos>=Pos2) and (Src1Pos>=Pos1) do begin
  175. cmp:=OnCompare(List[Src1Pos],List[Src2Pos]);
  176. if cmp>0 then begin
  177. MergeList[DestPos]:=List[Src1Pos];
  178. dec(Src1Pos);
  179. end else begin
  180. MergeList[DestPos]:=List[Src2Pos];
  181. dec(Src2Pos);
  182. end;
  183. dec(DestPos);
  184. end;
  185. while Src2Pos>=Pos2 do begin
  186. MergeList[DestPos]:=List[Src2Pos];
  187. dec(Src2Pos);
  188. dec(DestPos);
  189. end;
  190. for a:=DestPos+1 to Pos3 do
  191. List[a]:=MergeList[a];
  192. end;
  193. procedure Sort(StartPos, EndPos: PtrInt);
  194. // sort an interval in List. Use MergeList as work space.
  195. var
  196. mid: integer;
  197. begin
  198. if EndPos-StartPos<6 then begin
  199. SmallSort(StartPos,EndPos);
  200. end else begin
  201. mid:=(StartPos+EndPos) shr 1;
  202. Sort(StartPos,mid);
  203. Sort(mid+1,EndPos);
  204. Merge(StartPos,mid+1,EndPos);
  205. end;
  206. end;
  207. var
  208. Cnt: Integer;
  209. begin
  210. if (List=nil) then exit;
  211. Cnt:=List.Count;
  212. if StartIndex<0 then StartIndex:=0;
  213. if EndIndex>=Cnt then EndIndex:=Cnt-1;
  214. if StartIndex>=EndIndex then exit;
  215. MergeList:=GetMem(List.Count*SizeOf(Pointer));
  216. Sort(StartIndex,EndIndex);
  217. Freemem(MergeList);
  218. end;
  219. { TWebIDLParser }
  220. constructor TWebIDLParser.Create(aContext: TWEBIDLContext; aScanner: TWebIDLScanner);
  221. begin
  222. FScanner:=aScanner;
  223. FContext:=aContext;
  224. end;
  225. constructor TWebIDLParser.Create(aContext: TWEBIDLContext; aSource: UTF8String);
  226. begin
  227. FOwnsScanner:=True;
  228. Create(aContext,TWebIDLScanner.Create(aSource));
  229. end;
  230. destructor TWebIDLParser.Destroy;
  231. begin
  232. if FOwnsScanner then
  233. FreeAndNil(FScanner);
  234. inherited Destroy;
  235. end;
  236. function TWebIDLParser.CurrentToken: TIDLToken;
  237. begin
  238. Result:=FScanner.CurToken;
  239. end;
  240. function TWebIDLParser.GetToken: TIDLToken;
  241. begin
  242. Repeat
  243. Result:=FScanner.FetchToken;
  244. until Not (Result in [tkWhitespace,tkComment]);
  245. end;
  246. procedure TWebIDLParser.SetVersion(AValue: TWebIDLVersion);
  247. begin
  248. if FVersion=AValue then Exit;
  249. FVersion:=AValue;
  250. if Assigned(Scanner) then
  251. FScanner.Version:=FVersion;
  252. end;
  253. function TWebIDLParser.GetErrorPos: String;
  254. begin
  255. Result:='';
  256. If Assigned(FScanner) then
  257. Result:=Format('Error in IDL at line %d, pos %d: ',[FScanner.CurRow,FScanner.CurColumn]);
  258. end;
  259. procedure TWebIDLParser.Error(Msg: String);
  260. begin
  261. Raise EWebIDLParser.Create(GetErrorPos+Msg);
  262. end;
  263. procedure TWebIDLParser.Error(Fmt: String; Args: array of const);
  264. begin
  265. Raise EWebIDLParser.Create(GetErrorPos+Format(Fmt,Args));
  266. end;
  267. function TWebIDLParser.CurrentTokenString: UTF8String;
  268. begin
  269. Result:=Fscanner.CurTokenString;
  270. end;
  271. function TWebIDLParser.CurrentRow: integer;
  272. begin
  273. Result:=FScanner.CurRow;
  274. end;
  275. function TWebIDLParser.CurrentColumn: integer;
  276. begin
  277. Result:=FScanner.CurColumn;
  278. end;
  279. function TWebIDLParser.CurrentFile: string;
  280. begin
  281. Result:=FScanner.CurFile;
  282. end;
  283. procedure TWebIDLParser.CheckCurrentToken(aToken: TIDLToken);
  284. begin
  285. if (aToken<>CurrentToken) then
  286. Error(SErrInvalidToken,[GetTokenName(aToken),CurrentTokenString]);
  287. end;
  288. procedure TWebIDLParser.CheckCurrentTokens(aTokens: TIDLTokens);
  289. begin
  290. if Not (CurrentToken in aTokens) then
  291. Error('[20220725174524] '+SErrInvalidTokenList,[GetTokenNames(aTokens),CurrentTokenString]);
  292. end;
  293. function TWebIDLParser.ExpectToken(aToken: TIDLToken): TIDLToken;
  294. begin
  295. Result:=GetToken;
  296. CheckCurrentToken(aToken);
  297. end;
  298. function TWebIDLParser.ExpectTokens(aTokens: TIDLTokens): TIDLToken;
  299. begin
  300. Result:=GetToken;
  301. CheckCurrentTokens(aTokens);
  302. end;
  303. // We're at the [,{,( token when we enter here
  304. // On exit, we're on the terminator token.
  305. procedure TWebIDLParser.ParseExtAttributes(aList: TExtAttributeList; aTerminator: TIDLToken; ForSerializer : Boolean = False);
  306. Function AddSub(aTerm : TIDLToken) : String;
  307. Var
  308. L : TExtAttributeList;
  309. begin
  310. Result:=CurrentTokenString;
  311. L:=TExtAttributeList.Create;
  312. try
  313. ParseExtAttributes(L,aTerm,ForSerializer);
  314. Result:=Trim(Result+L.ToLine(',')+CurrentTokenString);
  315. finally
  316. L.Free;
  317. end;
  318. end;
  319. Procedure AddToCurrent(Var Current : UTF8String; Const aTerm : String);
  320. begin
  321. if (Current<>'') then
  322. Current:=Current+' ';
  323. Current:=Current+aTerm;
  324. end;
  325. Procedure AddToList(Var aTerm : UTF8String);
  326. begin
  327. ATerm:=Trim(ATerm);
  328. if (ATerm<>'') then
  329. begin
  330. AList.Add(aTerm);
  331. aTerm:='';
  332. end;
  333. end;
  334. Const
  335. OtherTokens = [tkNumberInteger,tkNumberFloat,tkIdentifier,tkString, {tkOther, tkMinus,}tkNegInfinity,
  336. tkDot,tkEllipsis,tkColon,tkSemicolon,tkLess,tkEqual,tkLarger,tkQuestionmark,tkStar,tkByteString,
  337. tkDOMString,tkInfinity,tkNan,tkUSVString,tkAny,tkboolean,tkbyte,tkDouble,tkFalse,tkFloat,tkComma,
  338. tkLong,tkNull,tkObject,tkOctet,tkOr,tkOptional,tkSequence,tkShort,tkTrue,tkUnsigned,tkVoid];
  339. Var
  340. tk : TIDLToken;
  341. ValidTokens : TIDLTokens;
  342. S : UTF8String;
  343. WasSub : Boolean;
  344. begin
  345. ValidTokens:=OtherTokens;
  346. if ForSerializer then
  347. ValidTokens:=ValidTokens + [tkInherit,tkGetter];
  348. tk:=GetToken;
  349. S:='';
  350. While Not (tk=aTerminator) do
  351. begin
  352. WasSub:=True;
  353. Case tk of
  354. tkEOF :
  355. CheckCurrentToken(aTerminator);
  356. tkSquaredBraceOpen:
  357. S:=S+AddSub(tkSquaredBraceClose);
  358. tkBracketOpen:
  359. S:=S+AddSub(tkBracketClose);
  360. tkCurlyBraceOpen :
  361. S:=S+AddSub(tkCurlyBraceClose);
  362. else
  363. WasSub:=False;
  364. // Check
  365. While (tk in ValidTokens) do
  366. begin
  367. AddToCurrent(S,CurrentTokenString);
  368. if tk=tkComma then
  369. AddToList(S);
  370. tk:=GetToken;
  371. end;
  372. end;
  373. if WasSub then
  374. tk:=GetToken;
  375. end;
  376. AddToList(S);
  377. end;
  378. function TWebIDLParser.AddDefinition(aParent: TIDLBaseObject;
  379. aClass: TIDLDefinitionClass; const AName: UTF8String): TIDLDefinition;
  380. begin
  381. Result:=Context.Add(aParent,aClass,AName,CurrentFile,CurrentRow,CurrentColumn);
  382. end;
  383. function TWebIDLParser.ParseExtAttributes: TExtAttributeList;
  384. var
  385. ok: Boolean;
  386. begin
  387. Result:=TExtAttributeList.Create;
  388. ok:=false;
  389. try
  390. ParseExtAttributes(Result,tkSquaredBraceClose);
  391. ok:=true;
  392. finally
  393. if not ok then
  394. FreeandNil(Result);
  395. end;
  396. end;
  397. function TWebIDLParser.ParseArgument(aParent : TIDLBaseObject): TIDLArgumentDefinition;
  398. (* On Entry, we're on the argument start
  399. on exit, on the token after the argument definition i.e. a comma or ) *)
  400. var
  401. ok: Boolean;
  402. begin
  403. Result:=TIDLArgumentDefinition(AddDefinition(aParent,TIDLArgumentDefinition,''));
  404. ok:=false;
  405. try
  406. if CurrentToken=tkOptional then
  407. begin
  408. Result.isOptional:=True;
  409. GetToken;
  410. end;
  411. if (CurrentToken=tkSquaredBraceOpen) then
  412. begin
  413. Result.Attributes:=ParseExtAttributes;
  414. GetToken;
  415. end;
  416. Result.ArgumentType:=ParseType(Result,False);
  417. if CurrentToken=tkEllipsis then
  418. begin
  419. Result.HasEllipsis:=True;
  420. GetToken;
  421. end;
  422. CheckCurrentTokens([tkIdentifier,tkOther,tkCallback,tkInterface]);
  423. Result.Name:=CurrentTokenString;
  424. ok:=true;
  425. finally
  426. if not ok then
  427. MaybeFree(Result,aParent);
  428. end;
  429. end;
  430. function TWebIDLParser.ParseFunction(aParent : TIDLBaseObject): TIDLFunctionDefinition;
  431. (* On Entry, we're on the function identifier, on exit, on the final ) *)
  432. var
  433. ok: Boolean;
  434. begin
  435. Result:=TIDLFunctionDefinition(AddDefinition(aParent,TIDLFunctionDefinition,CurrentTokenString));
  436. ok:=false;
  437. try
  438. ExpectToken(tkEqual);
  439. Result.ReturnType:=ParseType(Result,True,True);
  440. ParseArguments(Result.Arguments);
  441. ok:=true;
  442. finally
  443. if not ok then
  444. MaybeFree(Result,aParent);
  445. end;
  446. end;
  447. function TWebIDLParser.ParseCallBack(aParent : TIDLBaseObject): TIDLDefinition;
  448. var
  449. tk : TIDLToken;
  450. begin
  451. tk:=GetToken;
  452. Case tk of
  453. tkInterface :
  454. begin
  455. Result:=ParseInterface(aParent);
  456. TIDLInterfaceDefinition(Result).IsCallBack:=True;
  457. end;
  458. tkIdentifier :
  459. begin
  460. Result:=ParseFunction(aParent);
  461. With TIDLFunctionDefinition(Result) do
  462. Options:=Options+[foCallBack];
  463. end;
  464. else
  465. Error('[20220725174529] '+SErrInvalidTokenList,[GetTokenNames([tkInterface,tkIdentifier]),CurrentTokenString]);
  466. end;
  467. end;
  468. procedure TWebIDLParser.ParseArguments(aParent: TIDLBaseObject);
  469. Var
  470. A : TIDLArgumentDefinition;
  471. S : UTF8String;
  472. begin
  473. CheckCurrentToken(tkBracketOpen);
  474. GetToken;
  475. While (CurrentToken<>tkBracketClose) do
  476. begin
  477. A:=ParseArgument(aParent);
  478. ExpectTokens([tkEqual,tkComma,tkBracketClose]);
  479. if (CurrentToken=tkEqual) then
  480. begin
  481. ParseConstValue(S,True);
  482. A.HasDefaultValue:=True;
  483. A.DefaultValue:=S;
  484. GetToken;
  485. end;
  486. if (CurrentToken=tkComma) then
  487. GetToken;
  488. end;
  489. end;
  490. function TWebIDLParser.ParseOperation(aParent: TIDLBaseObject): TIDLFunctionDefinition;
  491. { On entry, we're on the type definition or on one of getter,setter,deleter,legacycaller,
  492. on exit, we're on the final ) }
  493. Const
  494. Specials = [tkGetter, tkSetter, tkDeleter, tkLegacyCaller, tkConstructor];
  495. OnlyGetter = [foGetter];
  496. OnlySetter = [foSetter];
  497. OnlyDeleter = [foDeleter];
  498. Var
  499. Opts : TFunctionOptions;
  500. FO : TFunctionOption;
  501. ok: Boolean;
  502. begin
  503. Opts:=[];
  504. While CurrentToken in Specials do
  505. begin
  506. Case CurrentToken of
  507. tkGetter : FO:=foGetter;
  508. tkSetter : FO:=foSetter;
  509. tkDeleter : FO:=foDeleter;
  510. tkLegacyCaller : FO:=foLegacyCaller;
  511. tkConstructor : fo:=foConstructor;
  512. end;
  513. Include(Opts,FO);
  514. GetToken;
  515. end;
  516. Result:=TIDLFunctionDefinition(AddDefinition(aParent,TIDLFunctionDefinition,''));
  517. ok:=false;
  518. try
  519. if (foConstructor in Opts) then
  520. Result.Name:='New'
  521. else
  522. begin
  523. Result.ReturnType:=ParseType(Result,False,True);
  524. case CurrentToken of
  525. tkIdentifier:
  526. begin
  527. Result.Name:=CurrentTokenString;
  528. GetToken;
  529. end;
  530. tkBracketOpen:
  531. if (Opts=OnlyGetter) or (Opts=OnlySetter) then
  532. // using default name getProperty/setProperty
  533. else if (Opts=OnlyDeleter) then
  534. // using default name
  535. else
  536. CheckCurrentToken(tkIdentifier);
  537. else
  538. CheckCurrentToken(tkIdentifier);
  539. end;
  540. end;
  541. ParseArguments(Result.Arguments);
  542. Result.Options:=Result.Options+Opts;
  543. ok:=true;
  544. finally
  545. if not ok then
  546. MaybeFree(Result,aParent);
  547. end;
  548. end;
  549. function TWebIDLParser.ParseStringifier(aParent: TIDLBaseObject): TIDLDefinition;
  550. (* On entry we're on stringifier, on exit, we're on the end of the definition, before ; *)
  551. Var
  552. tk : TIDLToken;
  553. begin
  554. tk:=GetToken;
  555. case tk of
  556. tkReadOnly,tkAttribute:
  557. begin
  558. Result:=ParseAttribute(aParent);
  559. With TIDLAttributeDefinition(Result) do
  560. Options:=Options+[aoStringifier];
  561. end;
  562. tkSemiColon:
  563. begin
  564. // stringifier;
  565. Result:=TIDLAttributeDefinition(AddDefinition(aParent,TIDLAttributeDefinition,''));
  566. With TIDLAttributeDefinition(Result) do
  567. Options:=Options+[aoStringifier];
  568. end;
  569. else
  570. begin
  571. Result:=ParseOperation(aParent);
  572. With TIDLFunctionDefinition(Result) do
  573. Options:=Options+[foStringifier];
  574. end;
  575. end;
  576. end;
  577. function TWebIDLParser.ParseIterable(aParent: TIDLBaseObject): TIDLIterableDefinition;
  578. Var
  579. T1,T2 : TIDLTypeDefDefinition;
  580. ok: Boolean;
  581. begin
  582. ExpectToken(tkLess);
  583. T1:=Nil;
  584. T2:=nil;
  585. Result:=TIDLIterableDefinition(AddDefinition(aParent,TIDLIterableDefinition,''));
  586. ok:=false;
  587. try
  588. T1:=ParseType(Result,True,True);
  589. if (CurrentToken=tkComma) then
  590. T2:=ParseType(Result,True,True);
  591. CheckCurrentToken(tkLarger);
  592. if T2=Nil then
  593. Result.ValueType:=T1
  594. else
  595. begin
  596. Result.ValueType:=T2;
  597. T2:=Nil;
  598. Result.KeyType:=T1;
  599. end;
  600. T1:=nil;
  601. ok:=true;
  602. finally
  603. if not ok then
  604. MaybeFree(Result,aParent);
  605. end;
  606. end;
  607. function TWebIDLParser.CompleteSimpleType(tk: TIDLToken; var S: UTF8String; out
  608. IsNull: Boolean): TIDLToken;
  609. begin
  610. Result:=tk;
  611. IsNull:=false;
  612. S:='';
  613. if (Result=tkUnsigned) then
  614. begin
  615. S:=CurrentTokenString+' ';
  616. Result:=GetToken;
  617. end
  618. else if (Result=tkUnrestricted) then
  619. begin
  620. S:=CurrentTokenString+' ';
  621. Result:=GetToken;
  622. end;
  623. // long
  624. S:=S+CurrentTokenString;
  625. if (Result<>tkLong) then
  626. Result:=GetToken
  627. else
  628. begin
  629. Result:=GetToken;
  630. // Long long
  631. if Result=tkLong then
  632. begin
  633. S:=S+' '+CurrentTokenString;
  634. Result:=GetToken;
  635. end;
  636. end;
  637. if Result=tkQuestionmark then
  638. begin
  639. IsNull:=True;
  640. Result:=GetToken;
  641. end;
  642. end;
  643. function TWebIDLParser.ParseMapLikeMember(aParent: TIDLBaseObject): TIDLMaplikeDefinition;
  644. var
  645. ok: Boolean;
  646. begin
  647. Result:=TIDLMaplikeDefinition(AddDefinition(aParent,TIDLMaplikeDefinition,''));
  648. ok:=false;
  649. try
  650. Result.TypeName:='maplike';
  651. ExpectToken(tkLess);
  652. Result.KeyType:=ParseType(Result,True,true);
  653. CheckCurrentToken(tkComma);
  654. Result.ValueType:=ParseType(Result,True,true);
  655. CheckCurrentToken(tkLarger);
  656. ok:=true;
  657. finally
  658. if not ok then
  659. MaybeFree(Result,aParent);
  660. end;
  661. end;
  662. function TWebIDLParser.ParseSetLikeMember(aParent: TIDLBaseObject): TIDLSetlikeDefinition;
  663. (* On Entry we're on setlike. On exit, we're on the > token *)
  664. var
  665. ok: Boolean;
  666. begin
  667. Result:=TIDLSetlikeDefinition(AddDefinition(aParent,TIDLSetlikeDefinition,''));
  668. ok:=false;
  669. try
  670. ExpectToken(tkLess);
  671. Result.ElementType:=ParseType(Result);
  672. Result.ElementType.Parent:=Result;
  673. CheckCurrentToken(tkLarger);
  674. ok:=true;
  675. finally
  676. if not ok then
  677. MaybeFree(Result,aParent);
  678. end;
  679. end;
  680. function TWebIDLParser.ParseRecordTypeDef(aParent: TIDLBaseObject): TIDLRecordDefinition;
  681. var
  682. ok: Boolean;
  683. begin
  684. Result:=TIDLRecordDefinition(AddDefinition(aParent,TIDLRecordDefinition,''));
  685. ok:=false;
  686. try
  687. Result.TypeName:='record';
  688. ExpectToken(tkLess);
  689. Result.KeyType:=ParseType(Result,True,true);
  690. CheckCurrentToken(tkComma);
  691. Result.ValueType:=ParseType(Result,True,true);
  692. CheckCurrentToken(tkLarger);
  693. ok:=true;
  694. finally
  695. if not ok then
  696. MaybeFree(Result,aParent);
  697. end;
  698. end;
  699. function TWebIDLParser.ParseConstValue(out aValue: UTF8String;
  700. aExtended: Boolean): TConstType;
  701. Const
  702. ValueTokens = [tkTrue,tkFalse,tkNumberFloat,tkNumberInteger,tkNull,tkInfinity,tkNegInfinity,tkNan];
  703. ExtendedTokens = [tkSquaredBraceOpen,tkString, tkCurlyBraceOpen];
  704. ExtendedValueTokens = ExtendedTokens + ValueTokens;
  705. AllowedTokens : Array[Boolean] of TIDLTokens = (ValueTokens,ExtendedValueTokens);
  706. begin
  707. ExpectTokens(AllowedTokens[aExtended]);
  708. aValue:=CurrentTokenString;
  709. Case CurrentToken of
  710. tkTrue,tkFalse : Result:=ctBoolean;
  711. tkNumberFloat : Result:=ctFloat;
  712. tkNumberInteger : Result:=ctInteger;
  713. tkNull : Result:=ctNull;
  714. tkNan : Result:=ctNan;
  715. tkInfinity : Result:=ctInfinity;
  716. tkNegInfinity : Result:=ctNegInfinity;
  717. tkString :
  718. If aExtended then
  719. Result:=ctString
  720. else
  721. Error(SErrUnExpectedToken,[CurrentTokenString]);
  722. tkSquaredBraceOpen :
  723. If aExtended then
  724. begin
  725. ExpectToken(tkSquaredBraceClose);
  726. aValue:=AValue+CurrentTokenString;
  727. Result:=ctEmptyArray
  728. end
  729. else
  730. Error(SErrUnExpectedToken,[CurrentTokenString]);
  731. tkCurlyBraceOpen :
  732. If aExtended then
  733. begin
  734. ExpectToken(tkCurlyBraceClose);
  735. aValue:=AValue+CurrentTokenString;
  736. Result:=ctEmptyObject
  737. end
  738. else
  739. Error(SErrUnExpectedToken,[CurrentTokenString]);
  740. end;
  741. end;
  742. function TWebIDLParser.ParseConst(aParent : TIDLBaseObject): TIDLConstDefinition;
  743. (*
  744. On Entry we're on const. On exit, we're before the ;
  745. *)
  746. Const
  747. PrefixTokens = [tkUnsigned,tkLong,tkUnrestricted];
  748. SingleTokens = [tkIdentifier,tkBoolean,tkByte,tkOctet,tkFloat,tkDouble,tkShort];
  749. TypeTokens = SingleTokens+PrefixTokens;
  750. Var
  751. S : UTF8String;
  752. isNull , ok: Boolean;
  753. tk : TIDLToken;
  754. begin
  755. Result:=Nil;
  756. isNull:=False;
  757. S:='';
  758. tk:=ExpectTokens(TypeTokens);
  759. // Unsigned
  760. Tk:=CompleteSimpleType(tk,S,IsNull);
  761. CheckCurrentToken(tkIdentifier);
  762. Result:=TIDLConstDefinition(AddDefinition(aParent,TIDLConstDefinition,CurrentTokenString));
  763. ok:=false;
  764. try
  765. Result.TypeName:=S;
  766. Result.AllowNull:=isNull;
  767. ExpectToken(tkEqual);
  768. Result.ConstType:=ParseConstValue(S,false);
  769. Result.Value:=S;
  770. ok:=true;
  771. finally
  772. if not ok then
  773. MaybeFree(Result,aParent);
  774. end;
  775. end;
  776. procedure TWebIDLParser.MaybeFree(Result: TIDLDefinition; aParent : TIDLBaseObject);
  777. begin
  778. if (AParent=Nil) then
  779. Result.Free
  780. else if (aParent is TIDLDefinitionList) and (Not TIDLDefinitionList(AParent).OwnsDefinitions) then
  781. Result.Free;
  782. end;
  783. function TWebIDLParser.ParseAttribute(aParent : TIDLBaseObject): TIDLAttributeDefinition;
  784. (*
  785. On Entry we're on readonly, inherit or attribute.
  786. On Exit, we're on the last token of the attribute definition, the name
  787. *)
  788. Var
  789. Options : TAttributeOptions;
  790. ok: Boolean;
  791. begin
  792. Options:=[];
  793. if CurrentToken=tkInherit then
  794. begin
  795. Include(Options,aoInherit);
  796. GetToken;
  797. end;
  798. if (CurrentToken=tkReadOnly) then
  799. begin
  800. Include(Options,aoReadOnly);
  801. GetToken;
  802. end;
  803. CheckCurrentToken(tkAttribute);
  804. Result:=TIDLAttributeDefinition(AddDefinition(aParent,TIDLAttributeDefinition,''));
  805. ok:=false;
  806. try
  807. Result.AttributeType:=ParseType(Result,True,True);
  808. CheckCurrentTokens([tkIdentifier,tkRequired]);
  809. Result.Name:=CurrentTokenString;
  810. Result.Options:=Options;
  811. ok:=true;
  812. finally
  813. if not ok then
  814. MaybeFree(Result,aParent);
  815. end;
  816. end;
  817. function TWebIDLParser.ParseStatic(aParent : TIDLBaseObject): TIDLDefinition;
  818. (* On Entry we're on static. On exit, we're on the end of the definition, before the ; *)
  819. Var
  820. A : TIDLAttributeDefinition;
  821. F : TIDLFunctionDefinition;
  822. tk : TIDLToken;
  823. begin
  824. tk:=GetToken;
  825. if (Tk in [tkReadonly,tkAttribute]) then
  826. begin
  827. A:=ParseAttribute(aParent);
  828. A.Options:=A.Options+[aoStatic];
  829. Result:=A;
  830. end
  831. else
  832. begin
  833. F:=ParseOperation(aParent);
  834. F.Options:=F.Options+[foStatic];
  835. Result:=F;
  836. end;
  837. end;
  838. function TWebIDLParser.ParseSerializer(aParent : TIDLBaseObject): TIDLSerializerDefinition;
  839. Var
  840. tk : TIDLToken;
  841. ok: Boolean;
  842. begin
  843. Result:=Nil;
  844. tk:=GetToken;
  845. if tk=tkSemiColon then
  846. exit;
  847. Result:=TIDLSerializerDefinition(AddDefinition(aParent,TIDLSerializerDefinition,''));
  848. ok:=false;
  849. try
  850. if tk<>tkEqual then
  851. begin
  852. Result.SerializerFunction:=ParseOperation(Result);
  853. Exit;
  854. end;
  855. ExpectTokens([tkSquaredBraceOpen,tkCurlyBraceOpen,tkIdentifier]);
  856. case CurrentToken of
  857. tkSquaredBraceOpen :
  858. begin
  859. ParseExtAttributes(Result.Identifiers,tkSquaredBraceClose,True);
  860. Result.Kind:=skArray;
  861. end;
  862. tkCurlyBraceOpen :
  863. begin
  864. ParseExtAttributes(Result.Identifiers,tkCurlyBraceClose,True);
  865. Result.Kind:=skObject;
  866. end;
  867. tkIdentifier :
  868. begin
  869. Result.Identifiers.Add(CurrentTokenString);
  870. Result.Kind:=skSingle;
  871. end;
  872. end;
  873. ok:=true;
  874. finally
  875. if not ok then
  876. MaybeFree(Result,aParent);
  877. end;
  878. end;
  879. function TWebIDLParser.ParseInterface(aParent : TIDLBaseObject): TIDLInterfaceDefinition;
  880. (*
  881. On Entry we're on interface. On exit, we're on the } character or the ; if it is an empty forward definition
  882. *)
  883. Var
  884. tk : TIDLToken;
  885. Attrs : TExtAttributeList;
  886. M : TIDLDefinition;
  887. isMixin,SemicolonSeen , ok: Boolean;
  888. begin
  889. Attrs:=nil;
  890. ExpectTokens([tkMixin,tkIdentifier]);
  891. isMixin:=CurrentToken=tkMixin;
  892. if CurrentToken=tkMixin then
  893. ExpectToken(tkIdentifier);
  894. Result:=TIDLInterfaceDefinition(AddDefinition(aParent,TIDLInterfaceDefinition,CurrentTokenString));
  895. ok:=false;
  896. try
  897. Result.IsMixin:=IsMixin;
  898. tk:=GetToken;
  899. if tk=tkSemiColon then
  900. begin
  901. // empty interface
  902. Result.IsForward:=true;
  903. exit;
  904. end;
  905. if tk=tkColon then
  906. begin
  907. ExpectToken(tkIdentifier);
  908. Result.ParentName:=CurrentTokenString;
  909. tk:=GetToken;
  910. end;
  911. CheckCurrentToken(tkCurlyBraceOpen);
  912. tk:=GetToken;
  913. While (tk<>tkCurlyBraceClose) do
  914. begin
  915. SemicolonSeen:=False;
  916. Attrs:=nil;
  917. M:=Nil;
  918. if tk=tkSquaredBraceOpen then
  919. begin
  920. Attrs:=ParseExtAttributes;
  921. tk:=GetToken;
  922. end;
  923. Case tk of
  924. tkConst : M:=ParseConst(Result.Members);
  925. tkSetLike : M:=ParseSetLikeMember(Result.Members);
  926. tkMapLike : M:=ParseMapLikeMember(Result.Members);
  927. tkReadOnly :
  928. begin
  929. Case GetToken of
  930. tkAttribute,tkInherit:
  931. begin
  932. M:=ParseAttribute(Result.Members);
  933. With TIDLAttributeDefinition(M) do
  934. Options:=Options+[aoReadOnly];
  935. end;
  936. tkMapLike:
  937. begin
  938. M:=ParseMapLikeMember (Result.Members);
  939. TIDLMapLikeDefinition(M).IsReadonly:=True;
  940. end;
  941. tkSetLike:
  942. begin
  943. M:=ParseSetLikeMember (Result.Members);
  944. TIDLSetLikeDefinition(M).IsReadonly:=True;
  945. end
  946. else
  947. CheckCurrentTokens([tkAttribute,tkInherit,tkMapLike,tkSetLike]);
  948. end;
  949. end;
  950. tkInherit,
  951. tkAttribute : M:=ParseAttribute(Result.Members);
  952. tkStatic : M:=ParseStatic(Result.Members);
  953. tkSerializer :
  954. begin
  955. M:=ParseSerializer(Result.Members);
  956. Result.HasSerializer:=True;
  957. SemicolonSeen:=M=Nil;
  958. end;
  959. tkStringifier :
  960. begin
  961. M:=ParseStringifier(Result.Members);
  962. Result.HasStringifier:=true;
  963. if CurrentToken=tkSemiColon then
  964. SemicolonSeen:=true;
  965. end;
  966. tkIterable : ParseIterable(Result.Members);
  967. else
  968. {
  969. tkGetter, tkSetter, tkDeleter, tkLegacyCaller
  970. }
  971. M:=ParseOperation(Result.Members);
  972. end;
  973. IF Assigned(M) then
  974. begin
  975. M.Attributes:=Attrs;
  976. Attrs:=Nil; // So it does not get freed in except
  977. end;
  978. if not SemicolonSeen then
  979. GetToken;
  980. CheckCurrentToken(tkSemicolon);
  981. tk:=GetToken;
  982. end;
  983. ok:=true;
  984. finally
  985. if not ok then
  986. begin
  987. FreeAndNil(Attrs);
  988. MaybeFree(Result,aParent);
  989. end;
  990. end;
  991. end;
  992. function TWebIDLParser.ParsePartial(aParent : TIDLBaseObject): TIDLStructuredDefinition;
  993. (* On entry, we're on Partial. On exit, we're on the } character *)
  994. begin
  995. Case GetToken of
  996. tkInterface : Result:=ParseInterface(aParent);
  997. tkDictionary : Result:=ParseDictionary(aParent);
  998. else
  999. Error('[20220725174539] '+SErrInvalidTokenList,[GetTokenNames([tkInterface,tkDictionary]),CurrentTokenString]);
  1000. end;
  1001. Result.IsPartial:=True;
  1002. end;
  1003. function TWebIDLParser.ParseImplementsOrIncludes(aParent: TIDLBaseObject): TIDLImplementsOrIncludesDefinition;
  1004. Var
  1005. aName : UTF8String;
  1006. begin
  1007. aName:=CurrentTokenString;
  1008. if version=v1 then
  1009. begin
  1010. ExpectToken(tkImplements);
  1011. Result:=ParseImplements(aName,aParent)
  1012. end
  1013. else
  1014. begin
  1015. ExpectTokens([tkImplements,tkIncludes]);
  1016. case CurrentToken of
  1017. tkIncludes: Result:=ParseIncludes(aName,aParent);
  1018. tkImplements: Result:=ParseImplements(aName,aParent);
  1019. end;
  1020. end;
  1021. end;
  1022. function TWebIDLParser.ParseEnum(aParent : TIDLBaseObject): TIDLEnumDefinition;
  1023. (* On entry, we're on enum. On exit, we're on the } character *)
  1024. Var
  1025. tk : TIDLToken;
  1026. begin
  1027. ExpectToken(tkIdentifier);
  1028. Result:=TIDLEnumDefinition(AddDefinition(aParent,TIDLEnumDefinition,CurrentTokenString));
  1029. ExpectToken(tkCurlyBraceOpen);
  1030. Repeat
  1031. tk:=ExpectTokens([tkCurlyBraceClose,tkString]);
  1032. if tk=tkString then
  1033. begin
  1034. Result.AddValue(CurrentTokenString);
  1035. tk:=ExpectTokens([tkCurlyBraceClose,tkComma]);
  1036. end;
  1037. Until (tk=tkCurlyBraceClose);
  1038. end;
  1039. function TWebIDLParser.ParseDictionaryMember(aParent : TIDLBaseObject): TIDLDictionaryMemberDefinition;
  1040. { On Entry, we're at the start of the member. This may be required, attributes or the type.
  1041. On Exit, we're on the ; }
  1042. Var
  1043. Attrs : TExtAttributeList;
  1044. tk : TIDLToken;
  1045. isReq , ok: Boolean;
  1046. S : UTF8String;
  1047. begin
  1048. Attrs:=Nil;
  1049. tk:=CurrentToken;
  1050. isReq:=(tk=tkRequired);
  1051. if IsReq then
  1052. tk:=GetToken;
  1053. if tk=tkSquaredBraceOpen then
  1054. begin
  1055. Attrs:=ParseExtAttributes;
  1056. tk:=GetToken;
  1057. isReq:=(tk=tkRequired);
  1058. if IsReq then
  1059. tk:=GetToken;
  1060. end;
  1061. Result:=TIDLDictionaryMemberDefinition(AddDefinition(aParent,TIDLDictionaryMemberDefinition,''));
  1062. ok:=false;
  1063. try
  1064. Result.Attributes:=Attrs;
  1065. Result.IsRequired:=isReq;
  1066. Result.MemberType:=ParseType(Result,False,True);
  1067. CheckCurrentToken(tkIdentifier);
  1068. Result.Name:=CurrentTokenString;
  1069. tk:=GetToken;
  1070. if tk=tkEqual then
  1071. begin
  1072. Result.DefaultValue:=TIDLConstDefinition(AddDefinition(Result,TIDLConstDefinition,''));
  1073. Result.DefaultValue.ConstType:=ParseConstValue(S,True);
  1074. Result.DefaultValue.Value:=S;
  1075. tk:=GetToken;
  1076. end;
  1077. CheckCurrentToken(tkSemicolon);
  1078. ok:=true;
  1079. finally
  1080. if not ok then
  1081. MaybeFree(Result,aParent);
  1082. end;
  1083. end;
  1084. function TWebIDLParser.ParseDictionary(aParent : TIDLBaseObject; AllowInheritance : Boolean = True): TIDLDictionaryDefinition;
  1085. (* On entry, we're on dictionary, on eexit, we're on { *)
  1086. Var
  1087. Name,ParentName : UTF8String;
  1088. tk : TIDLToken;
  1089. begin
  1090. ExpectToken(tkIdentifier);
  1091. Name:=CurrentTokenString;
  1092. tk:=GetToken;
  1093. if (tk=tkColon) then
  1094. begin
  1095. If Not AllowInheritance then
  1096. Error(SErrUnExpectedToken,[CurrentTokenString]);
  1097. ExpectToken(tkIdentifier);
  1098. ParentName:=CurrentTokenString;
  1099. tk:=GetToken;
  1100. end;
  1101. CheckCurrentToken(tkCurlyBraceOpen);
  1102. Result:=TIDLDictionaryDefinition(AddDefinition(aParent,TIDLDictionaryDefinition,Name));
  1103. Result.ParentName:=ParentName;
  1104. GetToken;
  1105. While (CurrentToken<>tkCurlyBraceClose) do
  1106. begin
  1107. ParseDictionaryMember(Result.Members);
  1108. CheckCurrentTokens([tkSemicolon,tkCurlyBraceClose]);
  1109. if (CurrentToken=tkSemicolon) then
  1110. GetToken;
  1111. end;
  1112. end;
  1113. function TWebIDLParser.ParseSequenceTypeDef(aParent : TIDLBaseObject): TIDLSequenceTypeDefDefinition;
  1114. (* On Entry we're on sequence. On exit, we're on the > token *)
  1115. var
  1116. ok: Boolean;
  1117. begin
  1118. Result:=TIDLSequenceTypeDefDefinition(AddDefinition(aParent,TIDLSequenceTypeDefDefinition,''));
  1119. ok:=false;
  1120. try
  1121. Result.TypeName:='sequence';
  1122. ExpectToken(tkLess);
  1123. Result.ElementType:=ParseType(Result);
  1124. Result.ElementType.Parent:=Result;
  1125. CheckCurrentToken(tkLarger);
  1126. ok:=true;
  1127. finally
  1128. if not ok then
  1129. MaybeFree(Result,aParent);
  1130. end;
  1131. end;
  1132. function TWebIDLParser.ParseUnionTypeDef(aParent : TIDLBaseObject): TIDLUnionTypeDefDefinition;
  1133. (* On Entry we're on (. On exit, we're on the ) token *)
  1134. Var
  1135. D : TIDLTypeDefDefinition;
  1136. tk : TIDLToken;
  1137. Attr : TExtAttributeList;
  1138. ok: Boolean;
  1139. begin
  1140. Attr:=Nil;
  1141. Result:=TIDLUnionTypeDefDefinition(AddDefinition(aParent,TIDLUnionTypeDefDefinition,''));
  1142. ok:=false;
  1143. try
  1144. Result.TypeName:='union';
  1145. Repeat
  1146. Attr:=Nil;
  1147. tk:=GetToken;
  1148. if Tk=tkSquaredBraceOpen then
  1149. begin
  1150. Attr:=ParseExtAttributes;
  1151. tk:=GetToken;
  1152. end;
  1153. D:=ParseType(Result.Union,False);
  1154. D.Attributes:=Attr;
  1155. Attr:=Nil;
  1156. if (D.TypeName='any') then
  1157. Error(SErrTypeNotAllowed,['any','union']);
  1158. CheckCurrentTokens([tkOr,tkBracketClose]);
  1159. tk:=CurrentToken;
  1160. until (tk=tkBracketClose);
  1161. ok:=true;
  1162. finally
  1163. if not ok then
  1164. begin
  1165. FreeAndNil(Attr);
  1166. MaybeFree(Result,aParent);
  1167. end;
  1168. end;
  1169. end;
  1170. function TWebIDLParser.ParsePromiseTypeDef(aParent: TIDLBaseObject): TIDLPromiseTypeDefDefinition;
  1171. (* On Entry we're on promise. On exit, we're on the > token *)
  1172. var
  1173. ok: Boolean;
  1174. begin
  1175. Result:=TIDLPromiseTypeDefDefinition(AddDefinition(aParent,TIDLPromiseTypeDefDefinition,''));
  1176. ok:=false;
  1177. try
  1178. Result.TypeName:='Promise';
  1179. ExpectToken(tkLess);
  1180. Result.ReturnType:=ParseType(Result,True,true);
  1181. CheckCurrentToken(tkLarger);
  1182. ok:=true;
  1183. finally
  1184. if not ok then
  1185. MaybeFree(Result,aParent);
  1186. end;
  1187. end;
  1188. function TWebIDLParser.ParseType(aParent : TIDLBaseObject; FetchFirst : Boolean = True; AllowExtraTypes : Boolean = False): TIDLTypeDefDefinition;
  1189. (* On Entry
  1190. if FetchFirst = true we're on "typedef", "(", "or" or "<" tokens.
  1191. if FetchFirst = true we're on the first actual token
  1192. On exit, we're on the first token after the type
  1193. *)
  1194. Const
  1195. SimplePrefixTokens = [tkUnsigned,tkLong,tkUnrestricted];
  1196. ComplexPrefixTokens = [tkSequence,tkPromise,tkBracketOpen,tkRecord,tkFrozenArray];
  1197. PrefixTokens = ComplexPrefixTokens+SimplePrefixTokens;
  1198. PrimitiveTokens = [tkBoolean,tkByte,tkOctet,tkFloat,tkDouble,tkShort,tkAny,tkObject];
  1199. IdentifierTokens = [tkIdentifier,tkByteString,tkUSVString,tkDOMString];
  1200. SimpleTypeTokens = PrimitiveTokens+IdentifierTokens;
  1201. TypeTokens = PrefixTokens+SimpleTypeTokens;
  1202. ExtraTypeTokens = TypeTokens +[{tkStringToken,}tkVoid];
  1203. EnforceRange = 'EnforceRange';
  1204. LegacyDOMString = 'LegacyNullToEmptyString';
  1205. Var
  1206. isNull , ok: Boolean;
  1207. typeName: UTF8String;
  1208. Allowed : TIDLTokens;
  1209. tk : TIDLToken;
  1210. begin
  1211. Result:=Nil;
  1212. ok:=false;
  1213. try
  1214. isNull:=False;
  1215. if FetchFirst then
  1216. tk:=GetToken
  1217. else
  1218. tk:=CurrentToken;
  1219. if tk=tkSquaredBraceOpen then
  1220. begin
  1221. ExpectToken(tkIdentifier);
  1222. case CurrentTokenString of
  1223. EnforceRange:
  1224. begin
  1225. // special: [EnforceRange] unsigned long
  1226. ExpectToken(tkSquaredBraceClose);
  1227. ExpectToken(tkunsigned);
  1228. ExpectToken(tklong);
  1229. Result:=TIDLTypeDefDefinition(AddDefinition(aParent,TIDLTypeDefDefinition,''));
  1230. Result.TypeName:='unsigned long';
  1231. Result.Attributes.Add(EnforceRange);
  1232. end;
  1233. LegacyDOMString:
  1234. begin
  1235. // special: [LegacyNullToEmptyString] DOMString
  1236. ExpectToken(tkSquaredBraceClose);
  1237. ExpectToken(tkDOMString);
  1238. Result:=TIDLTypeDefDefinition(AddDefinition(aParent,TIDLTypeDefDefinition,''));
  1239. Result.TypeName:='DOMString';
  1240. Result.Attributes.Add(LegacyDOMString);
  1241. end
  1242. else
  1243. Error(SErrInvalidToken,[LegacyDOMString,CurrentTokenString]);
  1244. end;
  1245. GetToken;
  1246. ok:=true;
  1247. exit;
  1248. end;
  1249. if AllowExtraTypes then
  1250. Allowed:=ExtraTypeTokens
  1251. else
  1252. Allowed:=TypeTokens;
  1253. CheckCurrentTokens(Allowed);
  1254. TypeName:=CurrentTokenString;
  1255. if (tk in SimplePrefixTokens) then
  1256. begin
  1257. tk:=CompleteSimpleType(tk,TypeName,isNull);
  1258. Result:=TIDLTypeDefDefinition(AddDefinition(aParent,TIDLTypeDefDefinition,''));
  1259. end
  1260. else
  1261. begin
  1262. Case tk of
  1263. tkRecord : Result:=ParseRecordTypeDef(aParent);
  1264. tkFrozenArray,
  1265. tkSequence : Result:=ParseSequenceTypeDef(aParent);
  1266. tkPromise : Result:=ParsePromiseTypeDef(aParent);
  1267. tkBracketOpen : Result:=ParseUnionTypeDef(aParent);
  1268. else
  1269. Result:=TIDLTypeDefDefinition(AddDefinition(aParent,TIDLTypeDefDefinition,''));
  1270. end;
  1271. tk:=GetToken;
  1272. end;
  1273. if Result.TypeName='' then
  1274. Result.TypeName:=TypeName;
  1275. // Null ?
  1276. if tk=tkQuestionmark then
  1277. begin
  1278. tk:=GetToken;
  1279. isNull:=True;
  1280. end;
  1281. Result.AllowNull:=isNull;
  1282. ok:=true;
  1283. finally
  1284. if not ok then
  1285. MaybeFree(Result,aParent);
  1286. end;
  1287. end;
  1288. function TWebIDLParser.ParseTypeDef(aParent : TIDLBaseObject): TIDLTypeDefDefinition;
  1289. (* On Entry we're on "typedef", "or" or "<" tokens. On exit, we're on the identifier *)
  1290. var
  1291. ok: Boolean;
  1292. begin
  1293. Result:=ParseType(aParent);
  1294. ok:=false;
  1295. try
  1296. CheckCurrentToken(tkIdentifier);
  1297. Result.Name:=CurrentTokenString;
  1298. ok:=true;
  1299. finally
  1300. if not ok then
  1301. MaybeFree(Result,aParent);
  1302. end;
  1303. end;
  1304. function TWebIDLParser.ParseImplements(const aName: UTF8String;
  1305. aParent: TIDLBaseObject): TIDLImplementsDefinition;
  1306. (* On entry, we're on the identifier for V1, we're. On Exit, we're on the last identifier *)
  1307. Var
  1308. N : UTF8String;
  1309. begin
  1310. if Version=V1 then
  1311. begin
  1312. N:=aName
  1313. end
  1314. else
  1315. N:=aName;
  1316. Result:=TIDLImplementsDefinition(AddDefinition(aParent,TIDLImplementsDefinition,N));
  1317. try
  1318. ExpectToken(tkIdentifier);
  1319. Result.ImplementedInterface:=CurrentTokenString;
  1320. except
  1321. MaybeFree(Result,aParent);
  1322. end;
  1323. end;
  1324. function TWebIDLParser.ParseIncludes(const aName: UTF8String;
  1325. aParent: TIDLBaseObject): TIDLIncludesDefinition;
  1326. (* On entry, we're on the identifier. On Exit, we're on the last identifier *)
  1327. begin
  1328. Result:=TIDLIncludesDefinition(AddDefinition(aParent,TIDLIncludesDefinition,aName));
  1329. try
  1330. ExpectToken(tkIdentifier);
  1331. Result.IncludedInterface:=CurrentTokenString;
  1332. except
  1333. MaybeFree(Result,aParent);
  1334. end;
  1335. end;
  1336. function TWebIDLParser.ParseDefinition(aParent : TIDLBaseObject): TIDLDefinition;
  1337. Var
  1338. tk : TIDLToken;
  1339. Attrs : TExtAttributeList;
  1340. begin
  1341. Result:=Nil;
  1342. Attrs:=Nil;
  1343. tk:=GetToken;
  1344. if tk=tkSquaredBraceOpen then
  1345. begin
  1346. Attrs:=ParseExtAttributes;
  1347. tk:=GetToken;
  1348. end;
  1349. Try
  1350. Case tk of
  1351. tkCallback : Result:=ParseCallBack(aParent);
  1352. tkInterface : Result:=ParseInterface(aParent);
  1353. tkDictionary : Result:=ParseDictionary(aParent);
  1354. tkPartial : Result:=ParsePartial(aParent);
  1355. tkEnum : Result:=ParseEnum(aParent);
  1356. tkTypeDef : Result:=ParseTypeDef(aParent);
  1357. tkIdentifier :
  1358. Result:=ParseImplementsOrIncludes(aParent);
  1359. tkEOF : exit;
  1360. else
  1361. Error(SErrUnExpectedToken,[CurrentTokenString]);
  1362. end;
  1363. if Assigned(Result) then
  1364. begin
  1365. Result.Attributes:=Attrs;
  1366. Attrs:=nil;
  1367. end;
  1368. finally
  1369. FreeAndNil(Attrs);
  1370. end;
  1371. if CurrentToken=tkSemiColon then exit;
  1372. ExpectToken(tkSemicolon);
  1373. end;
  1374. procedure TWebIDLParser.ParseDefinitions(aParent : TIDLBaseObject);
  1375. begin
  1376. Repeat
  1377. ParseDefinition(aParent);
  1378. Until (CurrentToken=tkEOF)
  1379. end;
  1380. procedure TWebIDLParser.Parse;
  1381. begin
  1382. ParseDefinitions(Context.Definitions);
  1383. end;
  1384. { TWebIDLContext }
  1385. constructor TWebIDLContext.Create(OwnsDefinitions : Boolean = True);
  1386. begin
  1387. FDefinitions:=TIDLDefinitionList.Create(Nil,OwnsDefinitions);
  1388. end;
  1389. destructor TWebIDLContext.Destroy;
  1390. begin
  1391. FreeAndNil(FDefinitions);
  1392. FreeAndNil(FHash);
  1393. inherited Destroy;
  1394. end;
  1395. function TWebIDLContext.FindDictionary(aName: UTF8String
  1396. ): TIDLDictionaryDefinition;
  1397. Var
  1398. I : Integer;
  1399. begin
  1400. I:=0;
  1401. Result:=Nil;
  1402. While (Result=Nil) and (I<FDefinitions.Count) do
  1403. begin
  1404. if (FDefinitions[i] is TIDLDictionaryDefinition) then
  1405. begin
  1406. Result:=TIDLDictionaryDefinition(FDefinitions[i]);
  1407. if (Result.Name<>aName) or (Result.IsPartial) then
  1408. Result:=nil;
  1409. end;
  1410. Inc(I);
  1411. end;
  1412. end;
  1413. function TWebIDLContext.FindInterface(aName: UTF8String
  1414. ): TIDLInterfaceDefinition;
  1415. Var
  1416. I : Integer;
  1417. begin
  1418. I:=0;
  1419. Result:=Nil;
  1420. While (Result=Nil) and (I<FDefinitions.Count) do
  1421. begin
  1422. if (FDefinitions[i] is TIDLInterfaceDefinition) then
  1423. begin
  1424. Result:=TIDLInterfaceDefinition(FDefinitions[i]);
  1425. if (Result.Name<>aName) or (Result.IsPartial) then
  1426. Result:=nil;
  1427. end;
  1428. Inc(I);
  1429. end;
  1430. end;
  1431. procedure TWebIDLContext.AppendDictionaryPartials;
  1432. Var
  1433. D : TIDLDefinition;
  1434. DD : TIDLDictionaryDefinition absolute D;
  1435. OD : TIDLDictionaryDefinition;
  1436. begin
  1437. For D in FDefinitions do
  1438. if (D is TIDLDictionaryDefinition) and (DD.IsPartial) then
  1439. begin
  1440. OD:=FindDictionary(DD.Name);
  1441. If (OD=Nil) then
  1442. Raise EWebIDLParser.CreateFmt(SErrDictionaryNotFound,[DD.Name]);
  1443. OD.Partials.Add(DD);
  1444. end;
  1445. end;
  1446. procedure TWebIDLContext.AppendInterfacePartials;
  1447. Var
  1448. D : TIDLDefinition;
  1449. ID : TIDLInterfaceDefinition absolute D;
  1450. OD : TIDLInterfaceDefinition;
  1451. begin
  1452. For D in FDefinitions do
  1453. if (D is TIDLInterfaceDefinition) and (ID.IsPartial) then
  1454. begin
  1455. OD:=FindInterface(ID.Name);
  1456. If (OD<>Nil) then
  1457. OD.Partials.Add(ID);
  1458. end;
  1459. end;
  1460. procedure TWebIDLContext.AppendInterfaceIncludes;
  1461. Var
  1462. D : TIDLDefinition;
  1463. ID : TIDLIncludesDefinition absolute D;
  1464. II,OI : TIDLInterfaceDefinition; // Includes and original
  1465. begin
  1466. For D in FDefinitions do
  1467. if (D is TIDLIncludesDefinition) then
  1468. begin
  1469. OI:=FindInterface(ID.Name);
  1470. If (OI=Nil) then
  1471. Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFound,[ID.Name]);
  1472. II:=FindInterface(ID.IncludedInterface);
  1473. If (II=Nil) then
  1474. begin
  1475. if Assigned(Aliases) and (Aliases.IndexOfName(ID.IncludedInterface)<>-1) then
  1476. OI.ParentName:=Aliases.Values[ID.IncludedInterface]
  1477. else
  1478. Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFoundFor,[ID.IncludedInterface,ID.Name]);
  1479. end
  1480. else
  1481. begin
  1482. II.IsInclude:=True;
  1483. OI.Partials.Add(II);
  1484. end
  1485. end;
  1486. // if there is a single include, no members and no parent, make it a descendent
  1487. For D in FDefinitions do
  1488. if (D is TIDLInterfaceDefinition) then
  1489. begin
  1490. OI:=D as TIDLInterfaceDefinition;
  1491. if (OI.ParentName='') and (OI.Partials.Count=1) then
  1492. if (OI.Partial[0] is TIDLInterfaceDefinition) then
  1493. begin
  1494. II:=OI.Partial[0] as TIDLInterfaceDefinition;
  1495. if II.IsInclude then
  1496. begin
  1497. // DoLog('Converting single include %s to parent class for %s',[II.Name,OI.Name]);
  1498. OI.ParentName:=II.Name;
  1499. OI.ParentInterface:=II;
  1500. OI.Partials.Clear;
  1501. end;
  1502. end;
  1503. end;
  1504. end;
  1505. procedure TWebIDLContext.AppendPartials;
  1506. begin
  1507. AppendDictionaryPartials;
  1508. AppendInterfacePartials;
  1509. end;
  1510. procedure TWebIDLContext.AppendIncludes;
  1511. begin
  1512. AppendInterfaceIncludes;
  1513. end;
  1514. type
  1515. TTopologicalIntf = class
  1516. Intf: TIDLInterfaceDefinition;
  1517. Parent: TIDLInterfaceDefinition;
  1518. Level: integer;
  1519. SrcPos: integer;
  1520. end;
  1521. function CompareTopologicalIntfWithLevelAndSrcPos(Data1, Data2: Pointer): integer;
  1522. var
  1523. A: TTopologicalIntf absolute Data1;
  1524. B: TTopologicalIntf absolute Data2;
  1525. begin
  1526. if A.Level<B.Level then
  1527. Result:=-1
  1528. else if A.Level>B.Level then
  1529. Result:=1
  1530. else if A.SrcPos<B.SrcPos then
  1531. Result:=-1
  1532. else if A.SrcPos>B.SrcPos then
  1533. Result:=1
  1534. else
  1535. Result:=0;
  1536. end;
  1537. function TWebIDLContext.GetInterfacesTopologically: TIDLDefinitionList;
  1538. var
  1539. List: TFPList; // list of TTopologicalIntf
  1540. function FindIntf(Intf: TIDLInterfaceDefinition): TTopologicalIntf;
  1541. var
  1542. i: Integer;
  1543. begin
  1544. for i:=0 to List.Count-1 do
  1545. if TTopologicalIntf(List[i]).Intf=Intf then
  1546. exit(TTopologicalIntf(List[i]));
  1547. Result:=nil;
  1548. end;
  1549. function FindParent(Top: TTopologicalIntf): TIDLInterfaceDefinition;
  1550. var
  1551. ParentIntf, IntfDef: TIDLInterfaceDefinition;
  1552. Def: TIDLDefinition;
  1553. begin
  1554. IntfDef:=Top.Intf;
  1555. if (Top.Parent=nil) and (IntfDef.ParentName<>'') then
  1556. begin
  1557. ParentIntf:=IntfDef.ParentInterface;
  1558. if ParentIntf<>nil then
  1559. Top.Parent:=ParentIntf
  1560. else
  1561. begin
  1562. Def:=FindDefinition(IntfDef.ParentName);
  1563. if Def is TIDLInterfaceDefinition then
  1564. Top.Parent:=TIDLInterfaceDefinition(Def)
  1565. else if Def=nil then
  1566. writeln('Warning: [TWebIDLContext.GetInterfacesTopologically] interface "'+IntfDef.Name+'" at '+GetDefPos(IntfDef)+', parent "'+IntfDef.ParentName+'" not found')
  1567. else
  1568. writeln('Error: [TWebIDLContext.GetInterfacesTopologically] interface "'+IntfDef.Name+'" at '+GetDefPos(IntfDef)+', parent "'+IntfDef.ParentName+'" is not an interface at '+GetDefPos(Def));
  1569. end;
  1570. end;
  1571. Result:=Top.Parent;
  1572. end;
  1573. function GetTopologicalLevel(Top: TTopologicalIntf): integer;
  1574. var
  1575. ParentTop: TTopologicalIntf;
  1576. IntfDef: TIDLInterfaceDefinition;
  1577. begin
  1578. IntfDef:=Top.Intf;
  1579. if Top.Level<0 then
  1580. begin
  1581. if Top.Parent=nil then
  1582. Top.Level:=0
  1583. else
  1584. begin
  1585. ParentTop:=FindIntf(Top.Parent);
  1586. if ParentTop=nil then
  1587. begin
  1588. writeln('Warning: [TWebIDLContext.GetInterfacesTopologically] interface "'+IntfDef.Name+'" at '+GetDefPos(IntfDef)+', parent "'+Top.Parent.Name+'" at '+GetDefPos(Top.Parent)+' not in definition list');
  1589. Top.Level:=0;
  1590. end
  1591. else
  1592. Top.Level:=GetTopologicalLevel(ParentTop)+1;
  1593. end;
  1594. end;
  1595. Result:=Top.Level;
  1596. end;
  1597. var
  1598. D: TIDLDefinition;
  1599. IntfDef: TIDLInterfaceDefinition;
  1600. Top: TTopologicalIntf;
  1601. i: Integer;
  1602. begin
  1603. Result:=nil;
  1604. List:=TFPList.Create;
  1605. try
  1606. // collect all interfaces
  1607. for D in Definitions do
  1608. if D is TIDLInterfaceDefinition then
  1609. begin
  1610. IntfDef:=TIDLInterfaceDefinition(D);
  1611. if IntfDef.IsPartial then continue;
  1612. Top:=TTopologicalIntf.Create;
  1613. Top.Intf:=IntfDef;
  1614. Top.Level:=-1;
  1615. Top.SrcPos:=List.Count;
  1616. List.Add(Top);
  1617. end;
  1618. // set parent interfaces
  1619. for i:=0 to List.Count-1 do
  1620. FindParent(TTopologicalIntf(List[i]));
  1621. // sort topologically (keeping source order)
  1622. for i:=0 to List.Count-1 do
  1623. GetTopologicalLevel(TTopologicalIntf(List[i]));
  1624. MergeSort(List,@CompareTopologicalIntfWithLevelAndSrcPos);
  1625. Result:=TIDLDefinitionList.Create(nil,false);
  1626. for i:=0 to List.Count-1 do
  1627. begin
  1628. Top:=TTopologicalIntf(List[i]);
  1629. Result.Add(Top.Intf);
  1630. end;
  1631. finally
  1632. List.Free;
  1633. end;
  1634. end;
  1635. procedure TWebIDLContext.ResolveParentTypes;
  1636. Var
  1637. D : TIDLDefinition;
  1638. ID : TIDLInterfaceDefinition absolute D;
  1639. DD : TIDLDictionaryDefinition absolute D;
  1640. begin
  1641. For D in FDefinitions do
  1642. if D is TIDLInterfaceDefinition then
  1643. begin
  1644. if (ID.ParentName<>'') then
  1645. ID.ParentInterface:=FindInterface(ID.ParentName);
  1646. end
  1647. else if D is TIDLDictionaryDefinition then
  1648. if (DD.ParentName<>'') then
  1649. DD.ParentDictionary:=FindDictionary(DD.ParentName);
  1650. end;
  1651. procedure TWebIDLContext.ResolveTypes;
  1652. begin
  1653. ResolveParentTypes;
  1654. end;
  1655. function TWebIDLContext.GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean
  1656. ): string;
  1657. begin
  1658. Result:='('+IntToStr(Def.Line)+','+IntToStr(Def.Column)+')';
  1659. if not WithoutFile then
  1660. Result:=Def.SrcFile+Result;
  1661. end;
  1662. function TWebIDLContext.IndexOfDefinition(const AName: String): Integer;
  1663. begin
  1664. Result:=Definitions.Count-1;
  1665. While (Result>=0) and (Definitions[Result].Name<>AName) do
  1666. Dec(Result);
  1667. end;
  1668. function TWebIDLContext.FindDefinition(const AName: String): TIDLDefinition;
  1669. Var
  1670. D : TIDLDefinition;
  1671. begin
  1672. if (FHash=Nil) then
  1673. begin
  1674. FHash:=TFPObjectHashTable.Create(False);
  1675. For D in Definitions do
  1676. if not D.IsExtension then
  1677. FHash.Add(D.Name,D);
  1678. end;
  1679. Result:=TIDLDefinition(FHash.Items[AName]);
  1680. end;
  1681. function TWebIDLContext.AsString(Full: Boolean): UTF8String;
  1682. begin
  1683. Result:=Definitions.AsString(';'+sLineBreak,'','','',Full,True);
  1684. end;
  1685. function TWebIDLContext.Add(aClass: TIDLDefinitionClass;
  1686. const AName: UTF8String; const aFile: string; aLine, aCol: integer
  1687. ): TIDLDefinition;
  1688. begin
  1689. Result:=Add(FDefinitions,aClass,AName,aFile,aLine,aCol);
  1690. end;
  1691. function TWebIDLContext.Add(aParent: TIDLBaseObject;
  1692. aClass: TIDLDefinitionClass; const AName: UTF8String; const aFile: string;
  1693. aLine, aCol: integer): TIDLDefinition;
  1694. begin
  1695. if Assigned(aParent) then
  1696. Result:=aParent.Add(aClass,aName,aFile,aLine,aCol)
  1697. else
  1698. Result:=aClass.Create(Nil,aName,aFile,aLine,aCol);
  1699. end;
  1700. end.