webidlparser.pp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510
  1. {
  2. This file is part of the Free Component Library
  3. WEBIDL source parser
  4. Copyright (c) 2018 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. interface
  14. uses
  15. Classes, SysUtils, Contnrs, webidlscanner, webidldefs;
  16. Type
  17. EWebIDLParser = Class(Exception);
  18. { TWebIDLContext }
  19. TWebIDLVersion = webidlscanner.TWebIDLVersion;
  20. TWebIDLContext = Class (TIDLBaseObject)
  21. private
  22. FAliases: TStrings;
  23. FDefinitions: TIDLDefinitionList;
  24. FHash : TFPObjectHashTable;
  25. Protected
  26. function FindDictionary(aName: UTF8String): TIDLDictionaryDefinition; virtual;
  27. function FindInterface(aName: UTF8String): TIDLInterfaceDefinition; virtual;
  28. procedure AppendDictionaryPartials; virtual;
  29. procedure AppendInterfacePartials; virtual;
  30. procedure AppendInterfaceIncludes; virtual;
  31. procedure ResolveParentTypes; virtual;
  32. Public
  33. Constructor Create(OwnsDefinitions : Boolean = True);
  34. Destructor Destroy; override;
  35. Procedure AppendPartials; virtual;
  36. Procedure AppendIncludes; virtual;
  37. Procedure ResolveTypes; virtual;
  38. function IndexOfDefinition(const AName: String): Integer;
  39. Function FindDefinition(const AName : String) : TIDLDefinition;
  40. Function AsString(Full: Boolean): UTF8String; override;
  41. Function Add(aClass : TIDLDefinitionClass; const AName : UTF8String) : TIDLDefinition; override;
  42. Function Add(aParent : TIDLBaseObject; aClass : TIDLDefinitionClass; const AName : UTF8String) : TIDLDefinition; virtual;
  43. Property Definitions : TIDLDefinitionList Read FDefinitions;
  44. Property Aliases : TStrings Read FAliases Write FAliases;
  45. end;
  46. { TWebIDLParser }
  47. TWebIDLParser = Class
  48. private
  49. FContext: TWebIDLContext;
  50. FScanner: TWebIDLScanner;
  51. FOwnsScanner : Boolean;
  52. FVersion: TWebIDLVersion;
  53. procedure SetVersion(AValue: TWebIDLVersion);
  54. Protected
  55. function GetErrorPos: String; virtual;
  56. // Error mechanism
  57. Procedure Error(Msg : String);
  58. Procedure Error(Fmt : String; Args : Array of const);
  59. // Scanner access. Only use this, do not use scanner directly.
  60. function CurrentToken: TIDLToken; virtual;
  61. function GetToken: TIDLToken; virtual;
  62. function CurrentTokenString: UTF8String;
  63. // Get next token, see if it is valid. Raise exception if not.
  64. procedure MaybeFree(Result: TIDLDefinition; aParent: TIDLBaseObject);
  65. Procedure CheckCurrentToken(aToken: TIDLToken);
  66. Procedure CheckCurrentTokens(aTokens: TIDLTokens);
  67. function ExpectToken(aToken: TIDLToken): TIDLToken;
  68. function ExpectTokens(aTokens: TIDLTokens): TIDLToken;
  69. // Attributes
  70. function ParseAttributes: TAttributeList;
  71. procedure ParseAttributes(aList: TAttributeList; aTerminator: TIDLToken; ForSerializer: Boolean=False); virtual;
  72. // Definitions
  73. // Type is a type without name of the type
  74. function ParseAttribute(aParent: TIDLBaseObject): TIDLAttributeDefinition; virtual;
  75. function ParseArgument(aParent: TIDLBaseObject): TIDLArgumentDefinition; virtual;
  76. procedure ParseArguments(aParent: TIDLBaseObject);virtual;
  77. function ParseFunction(aParent: TIDLBaseObject): TIDLFunctionDefinition; virtual;
  78. function ParseType(aParent: TIDLBaseObject; FetchFirst: Boolean=True; AllowExtraTypes : Boolean = False): TIDLTypeDefDefinition; virtual;
  79. function ParseDictionaryMember(aParent: TIDLBaseObject): TIDLDictionaryMemberDefinition; virtual;
  80. function CompleteSimpleType(tk: TIDLToken; Var S: UTF8String; out IsNull: Boolean): TIDLToken; virtual;
  81. function ParseMapLikeMember(aParent: TIDLBaseObject): TIDLMaplikeDefinition; virtual;
  82. function ParseSetLikeMember(aParent: TIDLBaseObject): TIDLSetlikeDefinition; virtual;
  83. function ParseRecordTypeDef(aParent: TIDLBaseObject): TIDLRecordDefinition; virtual;
  84. function ParsePromiseTypeDef(aParent: TIDLBaseObject): TIDLPromiseTypeDefDefinition; virtual;
  85. function ParseSequenceTypeDef(aParent : TIDLBaseObject): TIDLSequenceTypeDefDefinition; virtual;
  86. function ParseUnionTypeDef(aParent : TIDLBaseObject): TIDLUnionTypeDefDefinition; virtual;
  87. function ParseConstValue(out aValue: UTF8String; aExtended: Boolean): TConstType; virtual;
  88. function ParseConst(aParent: TIDLBaseObject ): TIDLConstDefinition; virtual;
  89. function ParseCallBack(aParent : TIDLBaseObject): TIDLDefinition; virtual;
  90. function ParseStringifier(aParent : TIDLBaseObject): TIDLDefinition; virtual;
  91. function ParseOperation(aParent: TIDLBaseObject): TIDLFunctionDefinition; virtual;
  92. function ParseSerializer(aParent: TIDLBaseObject): TIDLSerializerDefinition; virtual;
  93. function ParseStatic(aParent: TIDLBaseObject): TIDLDefinition;virtual;
  94. function ParseIterable(aParent : TIDLBaseObject): TIDLIterableDefinition; virtual;
  95. function ParseInterface(aParent : TIDLBaseObject): TIDLInterfaceDefinition; virtual;
  96. function ParseDictionary(aParent : TIDLBaseObject; AllowInheritance : Boolean = True): TIDLDictionaryDefinition; virtual;
  97. function ParseEnum(aParent : TIDLBaseObject): TIDLEnumDefinition; virtual;
  98. function ParseTypeDef(aParent : TIDLBaseObject): TIDLTypeDefDefinition; virtual;
  99. function ParsePartial(aParent : TIDLBaseObject): TIDLStructuredDefinition; virtual;
  100. function ParseImplementsOrIncludes(aParent: TIDLBaseObject): TIDLImplementsOrIncludesDefinition; virtual;
  101. function ParseImplements(Const aName : UTF8String; aParent : TIDLBaseObject): TIDLImplementsDefinition; virtual;
  102. function ParseIncludes(Const aName : UTF8String; aParent : TIDLBaseObject): TIDLIncludesDefinition; virtual;
  103. function ParseDefinition(aParent : TIDLBaseObject): TIDLDefinition; virtual;
  104. procedure ParseDefinitions(aParent : TIDLBaseObject); virtual;
  105. Public
  106. Constructor Create(aContext : TWEBIDLContext; aScanner : TWebIDLScanner); overload;
  107. Constructor Create(aContext : TWEBIDLContext; aSource : UTF8String);overload;
  108. Destructor Destroy; override;
  109. Procedure Parse;
  110. Property Scanner : TWebIDLScanner Read FScanner;
  111. Property Context : TWebIDLContext Read FContext;
  112. Property Version : TWebIDLVersion Read FVersion Write SetVersion;
  113. end;
  114. implementation
  115. Resourcestring
  116. SErrInvalidToken = 'Invalid token: expected "%s", got: "%s"';
  117. SErrInvalidTokenList = 'Invalid token: expected one of "%s", got: "%s"';
  118. // SExpectedOther = 'Unexpected token in attribute list: "%s".';
  119. SErrUnExpectedToken = 'Unexpected token : "%s"';
  120. SErrTypeNotAllowed = 'Type "%s" not allowed in "%s" type.';
  121. SErrDictionaryNotFound = 'Dictionary %s not found';
  122. SErrInterfaceNotFound = 'Interface %s not found';
  123. SErrInterfaceNotFoundfor = 'Included Interface %s not found for %s';
  124. { TWebIDLParser }
  125. constructor TWebIDLParser.Create(aContext: TWEBIDLContext; aScanner: TWebIDLScanner);
  126. begin
  127. FScanner:=aScanner;
  128. FContext:=aContext;
  129. end;
  130. constructor TWebIDLParser.Create(aContext: TWEBIDLContext; aSource: UTF8String);
  131. begin
  132. FOwnsScanner:=True;
  133. Create(aContext,TWebIDLScanner.Create(aSource));
  134. end;
  135. destructor TWebIDLParser.Destroy;
  136. begin
  137. if FOwnsScanner then
  138. FreeAndNil(FScanner);
  139. inherited Destroy;
  140. end;
  141. function TWebIDLParser.CurrentToken: TIDLToken;
  142. begin
  143. Result:=FScanner.CurToken;
  144. end;
  145. function TWebIDLParser.GetToken: TIDLToken;
  146. begin
  147. Repeat
  148. Result:=FScanner.FetchToken;
  149. until Not (Result in [tkWhitespace,tkComment]);
  150. end;
  151. procedure TWebIDLParser.SetVersion(AValue: TWebIDLVersion);
  152. begin
  153. if FVersion=AValue then Exit;
  154. FVersion:=AValue;
  155. if Assigned(Scanner) then
  156. FScanner.Version:=FVersion;
  157. end;
  158. function TWebIDLParser.GetErrorPos: String;
  159. begin
  160. Result:='';
  161. If Assigned(FScanner) then
  162. Result:=Format('Error in IDL at line %d, pos %d: ',[FScanner.CurRow,FScanner.CurColumn]);
  163. end;
  164. procedure TWebIDLParser.Error(Msg: String);
  165. begin
  166. Raise EWebIDLParser.Create(GetErrorPos+Msg);
  167. end;
  168. procedure TWebIDLParser.Error(Fmt: String; Args: array of const);
  169. begin
  170. Raise EWebIDLParser.Create(GetErrorPos+Format(Fmt,Args));
  171. end;
  172. function TWebIDLParser.CurrentTokenString: UTF8String;
  173. begin
  174. Result:=Fscanner.CurTokenString;
  175. end;
  176. procedure TWebIDLParser.CheckCurrentToken(aToken: TIDLToken);
  177. begin
  178. if (aToken<>CurrentToken) then
  179. Error(SErrInvalidToken,[GetTokenName(aToken),CurrenttokenString]);
  180. end;
  181. procedure TWebIDLParser.CheckCurrentTokens(aTokens: TIDLTokens);
  182. begin
  183. if Not (CurrentToken in aTokens) then
  184. Error(SErrInvalidTokenList,[GetTokenNames(aTokens),CurrentTokenString]);
  185. end;
  186. function TWebIDLParser.ExpectToken(aToken: TIDLToken): TIDLToken;
  187. begin
  188. Result:=GetToken;
  189. CheckCurrentToken(aToken);
  190. end;
  191. function TWebIDLParser.ExpectTokens(aTokens: TIDLTokens): TIDLToken;
  192. begin
  193. Result:=GetToken;
  194. CheckCurrentTokens(aTokens);
  195. end;
  196. // We're at the [,{,( token when we enter here
  197. // On exit, we're on the terminator token.
  198. procedure TWebIDLParser.ParseAttributes(aList: TAttributeList; aTerminator: TIDLToken; ForSerializer : Boolean = False);
  199. Function AddSub(aTerm : TIDLTOken) : String;
  200. Var
  201. L : TAttributeList;
  202. begin
  203. Result:=CurrentTokenString;
  204. L:=TAttributeList.Create;
  205. try
  206. ParseAttributes(L,aTerm,ForSerializer);
  207. Result:=Trim(Result+L.ToLine(',')+CurrentTokenString);
  208. finally
  209. L.Free;
  210. end;
  211. end;
  212. Procedure AddToCurrent(Var Current : UTF8String; Const aTerm : String);
  213. begin
  214. if (Current<>'') then
  215. Current:=Current+' ';
  216. Current:=Current+aterm;
  217. end;
  218. Procedure AddToList(Var aTerm : UTF8String);
  219. begin
  220. ATerm:=Trim(ATerm);
  221. if (ATerm<>'') then
  222. begin
  223. AList.Add(aTerm);
  224. aTerm:='';
  225. end;
  226. end;
  227. Const
  228. OtherTokens = [tkNumberInteger,tkNumberFloat,tkIdentifier,tkString, {tkOther, tkMinus,}tkNegInfinity,
  229. tkDot,tkEllipsis,tkColon,tkSemicolon,tkLess,tkEqual,tkLarger,tkQuestionmark,tkByteString,
  230. tkDOMString,tkInfinity,tkNan,tkUSVString,tkAny,tkboolean,tkbyte,tkDouble,tkFalse,tkFloat,tkComma,
  231. tkLong,tkNull,tkObject,tkOctet,tkOr,tkOptional,tkSequence,tkShort,tkTrue,tkUnsigned,tkVoid];
  232. Var
  233. tk : TIDLToken;
  234. ValidTokens : TIDLTokens;
  235. S : UTF8String;
  236. WasSub : Boolean;
  237. begin
  238. ValidTokens:=OtherTokens;
  239. if ForSerializer then
  240. ValidTokens:=ValidTokens + [tkInherit,tkGetter];
  241. tk:=GetToken;
  242. S:='';
  243. While Not (tk=aTerminator) do
  244. begin
  245. WasSub:=True;
  246. Case tk of
  247. tkEOF :
  248. CheckCurrentToken(aTerminator);
  249. tkSquaredBraceOpen:
  250. S:=S+AddSub(tkSquaredBraceClose);
  251. tkBracketOpen:
  252. S:=S+AddSub(tkBracketClose);
  253. tkCurlyBraceOpen :
  254. S:=S+AddSub(tkCurlyBraceClose);
  255. else
  256. WasSub:=False;
  257. // Check
  258. While (tk in ValidTokens) do
  259. begin
  260. AddToCurrent(S,CurrentTokenString);
  261. if tk=tkComma then
  262. AddToList(S);
  263. tk:=GetToken;
  264. end;
  265. end;
  266. if WasSub then
  267. tk:=GetToken;
  268. end;
  269. AddToList(S);
  270. end;
  271. function TWebIDLParser.ParseAttributes: TAttributeList;
  272. begin
  273. Result:=TAttributeList.Create;
  274. try
  275. ParseAttributes(Result,tkSquaredBraceClose);
  276. except
  277. FreeandNil(Result);
  278. Raise;
  279. end;
  280. end;
  281. function TWebIDLParser.ParseArgument(aParent : TIDLBaseObject): TIDLArgumentDefinition;
  282. (* On Entry, we're on the argument start
  283. on exit, on the token after the argument definition i.e. a comma or ) *)
  284. begin
  285. Result:=TIDLArgumentDefinition(Context.Add(aParent,TIDLArgumentDefinition,''));
  286. try
  287. if (CurrentToken=tkSquaredBraceOpen) then
  288. begin
  289. Result.Attributes:=ParseAttributes;
  290. getToken;
  291. end;
  292. if CurrentToken=tkOptional then
  293. begin
  294. Result.isOptional:=True;
  295. GetToken;
  296. end;
  297. Result.ArgumentType:=ParseType(Result,False);
  298. if CurrentToken=tkEllipsis then
  299. begin
  300. Result.HasEllipsis:=True;
  301. GetToken;
  302. end;
  303. CheckCurrentToken(tkIdentifier);
  304. Result.Name:=CurrentTokenString;
  305. except
  306. MaybeFree(Result,aParent);
  307. Raise;
  308. end;
  309. end;
  310. function TWebIDLParser.ParseFunction(aParent : TIDLBaseObject): TIDLFunctionDefinition;
  311. (* On Entry, we're on the function identifier, on exit, on the final ) *)
  312. begin
  313. Result:=TIDLFunctionDefinition(Context.Add(aParent,TIDLFunctionDefinition,CurrentTokenString));
  314. try
  315. ExpectToken(tkEqual);
  316. Result.ReturnType:=ParseType(Result,True,True);
  317. ParseArguments(Result.Arguments);
  318. except
  319. MaybeFree(Result,aParent);
  320. Raise;
  321. end;
  322. end;
  323. function TWebIDLParser.ParseCallBack(aParent : TIDLBaseObject): TIDLDefinition;
  324. var
  325. tk : TIDLToken;
  326. begin
  327. tk:=GetToken;
  328. Case tk of
  329. tkInterface :
  330. begin
  331. Result:=ParseInterface(aParent);
  332. TIDLInterfaceDefinition(Result).IsCallBack:=True;
  333. end;
  334. tkIdentifier :
  335. begin
  336. Result:=ParseFunction(aParent);
  337. With TIDLFunctionDefinition(Result) do
  338. Options:=Options+[foCallBack];
  339. end;
  340. else
  341. Error(SErrInvalidTokenList,[GetTokenNames([tkInterface,tkIdentifier])]);
  342. end;
  343. end;
  344. procedure TWebIDLParser.ParseArguments(aParent: TIDLBaseObject);
  345. Var
  346. A : TIDLArgumentDefinition;
  347. S : UTF8String;
  348. begin
  349. CheckCurrentToken(tkBracketOpen);
  350. GetToken;
  351. While (CurrentToken<>tkBracketClose) do
  352. begin
  353. A:=ParseArgument(aParent);
  354. ExpectTokens([tkEqual,tkComma,tkBracketClose]);
  355. if (CurrentToken=tkEqual) then
  356. begin
  357. ParseConstValue(S,True);
  358. A.HasDefaultValue:=True;
  359. A.DefaultValue:=S;
  360. GetToken;
  361. end;
  362. if (CurrentToken=tkComma) then
  363. GetToken;
  364. end;
  365. end;
  366. function TWebIDLParser.ParseOperation(aParent: TIDLBaseObject): TIDLFunctionDefinition;
  367. { On entry, we're on the type definition or on one of getter,setter,deleter,legacycaller,
  368. on exit, we're on the final ) }
  369. Const
  370. Specials = [tkGetter, tkSetter, tkDeleter, tkLegacyCaller, tkConstructor];
  371. Var
  372. Opts : TFunctionOptions;
  373. FO : TFunctionOption;
  374. begin
  375. Opts:=[];
  376. While CurrentToken in Specials do
  377. begin
  378. Case CurrentToken of
  379. tkGetter : FO:=foGetter;
  380. tkSetter : FO:=foSetter;
  381. tkDeleter : FO:=foDeleter;
  382. tkLegacyCaller : FO:=foLegacyCaller;
  383. tkConstructor : fo:=foConstructor;
  384. end;
  385. Include(Opts,FO);
  386. GetToken;
  387. end;
  388. Result:=TIDLFunctionDefinition(Context.Add(aParent,TIDLFunctionDefinition,''));
  389. try
  390. if (foConstructor in Opts) then
  391. Result.Name:='New'
  392. else
  393. begin
  394. Result.ReturnType:=ParseType(Result,False,True);
  395. CheckCurrentToken(tkIdentifier);
  396. Result.Name:=CurrentTokenString;
  397. GetToken;
  398. end;
  399. ParseArguments(Result.Arguments);
  400. Result.Options:=Result.Options+Opts;
  401. except
  402. MaybeFree(Result,aParent);
  403. Raise;
  404. end;
  405. end;
  406. function TWebIDLParser.ParseStringifier(aParent: TIDLBaseObject): TIDLDefinition;
  407. (* On entry we're on stringifier, on exit, we're on the end of the definition, before ; *)
  408. Var
  409. tk : TIDLToken;
  410. begin
  411. tk:=getToken;
  412. if tk in [tkReadOnly,tkAttribute] then
  413. begin
  414. Result:=ParseAttribute(aParent);
  415. With TIDLAttributeDefinition(result) do
  416. Options:=Options+[aoStringifier];
  417. end
  418. else
  419. begin
  420. Result:=ParseOperation(aParent);
  421. With TIDLFunctionDefinition(result) do
  422. Options:=Options+[foStringifier];
  423. end;
  424. end;
  425. function TWebIDLParser.ParseIterable(aParent: TIDLBaseObject): TIDLIterableDefinition;
  426. Var
  427. T1,T2 : TIDLTypeDefDefinition;
  428. begin
  429. ExpectToken(tkLess);
  430. T1:=Nil;
  431. T2:=nil;
  432. try
  433. Result:=TIDLIterableDefinition(Context.Add(aParent,TIDLIterableDefinition,''));
  434. T1:=ParseType(Result,True,True);
  435. if (CurrentToken=tkComma) then
  436. T2:=ParseType(Result,True,True);
  437. CheckCurrentToken(tkLarger);
  438. if T2=Nil then
  439. Result.ValueType:=T1
  440. else
  441. begin
  442. Result.ValueType:=T2;
  443. T2:=Nil;
  444. Result.KeyType:=T1;
  445. end;
  446. T1:=nil;
  447. except
  448. MaybeFree(Result,aParent);
  449. Raise;
  450. end;
  451. end;
  452. function TWebIDLParser.CompleteSimpleType(tk: TIDLToken; Var S: UTF8String; out
  453. IsNull: Boolean): TIDLToken;
  454. begin
  455. Result:=tk;
  456. S:='';
  457. if (Result=tkUnsigned) then
  458. begin
  459. S:=CurrentTokenString+' ';
  460. Result:=GetToken;
  461. end
  462. else if (Result=tkUnrestricted) then
  463. begin
  464. S:=CurrentTokenString+' ';
  465. Result:=GetToken;
  466. end;
  467. // long
  468. S:=S+CurrentTokenString;
  469. if (Result<>tkLong) then
  470. Result:=GetToken
  471. else
  472. begin
  473. Result:=GetToken;
  474. // Long long
  475. if Result=tkLong then
  476. begin
  477. S:=S+' '+CurrentTokenString;
  478. Result:=GetToken;
  479. end;
  480. end;
  481. if Result=tkQuestionmark then
  482. begin
  483. IsNull:=True;
  484. Result:=GetToken;
  485. end;
  486. end;
  487. function TWebIDLParser.ParseMapLikeMember(aParent: TIDLBaseObject): TIDLMaplikeDefinition;
  488. begin
  489. Result:=TIDLMaplikeDefinition(Context.Add(aParent,TIDLMaplikeDefinition,''));
  490. try
  491. Result.TypeName:='maplike';
  492. ExpectToken(tkLess);
  493. Result.KeyType:=ParseType(Result,True,true);
  494. CheckCurrentToken(tkComma);
  495. Result.ValueType:=ParseType(Result,True,true);
  496. CheckCurrentToken(tkLarger);
  497. except
  498. MaybeFree(Result,aParent);
  499. Raise;
  500. end;
  501. end;
  502. function TWebIDLParser.ParseSetLikeMember(aParent: TIDLBaseObject): TIDLSetlikeDefinition;
  503. (* On Entry we're on setlike. On exit, we're on the > token *)
  504. begin
  505. Result:=TIDLSetlikeDefinition(Context.Add(aParent,TIDLSetlikeDefinition,''));
  506. try
  507. ExpectToken(tkLess);
  508. Result.ElementType:=ParseType(Result);
  509. Result.ElementType.Parent:=Result;
  510. CheckCurrentToken(tkLarger);
  511. except
  512. MaybeFree(Result,aParent);
  513. Raise;
  514. end;
  515. end;
  516. function TWebIDLParser.ParseRecordTypeDef(aParent: TIDLBaseObject): TIDLRecordDefinition;
  517. begin
  518. Result:=TIDLRecordDefinition(Context.Add(aParent,TIDLRecordDefinition,''));
  519. try
  520. Result.TypeName:='record';
  521. ExpectToken(tkLess);
  522. Result.KeyType:=ParseType(Result,True,true);
  523. CheckCurrentToken(tkComma);
  524. Result.ValueType:=ParseType(Result,True,true);
  525. CheckCurrentToken(tkLarger);
  526. except
  527. MaybeFree(Result,aParent);
  528. Raise;
  529. end;
  530. end;
  531. function TWebIDLParser.ParseConstValue(out aValue: UTF8String;
  532. aExtended: Boolean): TConstType;
  533. Const
  534. ValueTokens = [tkTrue,tkFalse,tkNumberFloat,tkNumberInteger,tkNull,tkInfinity,tkNegInfinity,tkNan];
  535. ExtendedTokens = [tkSquaredBraceOpen,tkString, tkCurlyBraceOpen];
  536. ExtendedValueTokens = ExtendedTokens + ValueTokens;
  537. AllowedTokens : Array[Boolean] of TIDLTokens = (ValueTokens,ExtendedValueTokens);
  538. begin
  539. ExpectTokens(AllowedTokens[aExtended]);
  540. aValue:=CurrentTokenString;
  541. Case CurrentToken of
  542. tkTrue,tkFalse : Result:=ctBoolean;
  543. tkNumberFloat : Result:=ctFloat;
  544. tkNumberInteger : Result:=ctInteger;
  545. tkNull : Result:=ctNull;
  546. tkNan : Result:=ctNan;
  547. tkInfinity : Result:=ctInfinity;
  548. tkNegInfinity : Result:=ctNegInfinity;
  549. tkString :
  550. If aExtended then
  551. Result:=ctString
  552. else
  553. Error(SErrUnExpectedToken,[CurrentTokenString]);
  554. tkSquaredBraceOpen :
  555. If aExtended then
  556. begin
  557. ExpectToken(tkSquaredBraceClose);
  558. aValue:=AValue+CurrentTokenString;
  559. Result:=ctEmptyArray
  560. end
  561. else
  562. Error(SErrUnExpectedToken,[CurrentTokenString]);
  563. tkCurlyBraceOpen :
  564. If aExtended then
  565. begin
  566. ExpectToken(tkCurlyBraceClose);
  567. aValue:=AValue+CurrentTokenString;
  568. Result:=ctEmptyObject
  569. end
  570. else
  571. Error(SErrUnExpectedToken,[CurrentTokenString]);
  572. end;
  573. end;
  574. function TWebIDLParser.ParseConst(aParent : TIDLBaseObject): TIDLConstDefinition;
  575. (*
  576. On Entry we're on const. On exit, we're before the ;
  577. *)
  578. Const
  579. PrefixTokens = [tkUnsigned,tkLong,tkUnrestricted];
  580. SingleTokens = [tkIdentifier,tkBoolean,tkByte,tkOctet,tkFloat,tkDouble,tkShort];
  581. TypeTokens = SingleTokens+PrefixTokens;
  582. Var
  583. S : UTF8String;
  584. isNull : Boolean;
  585. tk : TIDLToken;
  586. begin
  587. Result:=Nil;
  588. isNull:=False;
  589. S:='';
  590. tk:=ExpectTokens(TypeTokens);
  591. // Unsigned
  592. Tk:=CompleteSimpleType(tk,S,IsNull);
  593. CheckCurrentToken(tkIdentifier);
  594. Result:=TIDLConstDefinition(Context.Add(aParent,TIDLConstDefinition,CurrentTokenString));
  595. try
  596. Result.TypeName:=S;
  597. Result.AllowNull:=isNull;
  598. ExpectToken(tkEqual);
  599. Result.ConstType:=ParseConstValue(S,false);
  600. Result.Value:=S;
  601. except
  602. MaybeFree(Result,aParent);
  603. Raise;
  604. end;
  605. end;
  606. procedure TWebIDLParser.MaybeFree(Result: TIDLDefinition; aParent : TIDLBaseObject);
  607. begin
  608. if (AParent=Nil) then
  609. Result.Free
  610. else if (aParent is TIDLDefinitionList) and (Not TIDLDefinitionList(AParent).OwnsDefinitions) then
  611. Result.Free;
  612. end;
  613. function TWebIDLParser.ParseAttribute(aParent : TIDLBaseObject): TIDLAttributeDefinition;
  614. (*
  615. On Entry we're on readonly, inherit or attribute.
  616. On Exit, we're on the last token of the attribute definition, the name
  617. *)
  618. Var
  619. Options : TAttributeOptions;
  620. begin
  621. Options:=[];
  622. if CurrentToken=tkInherit then
  623. begin
  624. Include(Options,aoInherit);
  625. GetToken;
  626. end;
  627. if (CurrentToken=tkReadOnly) then
  628. begin
  629. Include(Options,aoReadOnly);
  630. GetToken;
  631. end;
  632. CheckCurrentToken(tkAttribute);
  633. Result:=TIDLAttributeDefinition(Context.Add(aParent,TIDLAttributeDefinition,''));
  634. try
  635. Result.AttributeType:=ParseType(Result,True,True);
  636. CheckCurrentToken(tkIdentifier);
  637. Result.Name:=CurrentTokenString;
  638. Result.Options:=Options;
  639. except
  640. MaybeFree(Result,aParent);
  641. Raise;
  642. end;
  643. end;
  644. function TWebIDLParser.ParseStatic(aParent : TIDLBaseObject): TIDLDefinition;
  645. (* On Entry we're on static. On exit, we're on the end of the definition, before the ; *)
  646. Var
  647. A : TIDLAttributeDefinition;
  648. F : TIDLFunctionDefinition;
  649. tk : TIDLToken;
  650. begin
  651. tk:=GetToken;
  652. if (Tk in [tkReadonly,tkAttribute]) then
  653. begin
  654. A:=ParseAttribute(aParent);
  655. A.Options:=A.Options+[aoStatic];
  656. Result:=A;
  657. end
  658. else
  659. begin
  660. F:=ParseOperation(aParent);
  661. F.Options:=F.Options+[foStatic];
  662. Result:=F;
  663. end;
  664. end;
  665. function TWebIDLParser.ParseSerializer(aParent : TIDLBaseObject): TIDLSerializerDefinition;
  666. Var
  667. tk : TIDLToken;
  668. begin
  669. Result:=Nil;
  670. tk:=GetToken;
  671. if tk=tkSemiColon then
  672. exit;
  673. Result:=TIDLSerializerDefinition(Context.Add(aParent,TIDLSerializerDefinition,''));
  674. try
  675. if tk<>tkEqual then
  676. begin
  677. Result.SerializerFunction:=ParseOperation(Result);
  678. Exit;
  679. end;
  680. ExpectTokens([tkSquaredBraceOpen,tkCurlyBraceOpen,tkIdentifier]);
  681. case CurrentToken of
  682. tkSquaredBraceOpen :
  683. begin
  684. ParseAttributes(Result.Identifiers,tkSquaredBraceClose,True);
  685. Result.Kind:=skArray;
  686. end;
  687. tkCurlyBraceOpen :
  688. begin
  689. ParseAttributes(Result.Identifiers,tkCurlyBraceClose,True);
  690. Result.Kind:=skObject;
  691. end;
  692. tkIdentifier :
  693. begin
  694. Result.Identifiers.Add(CurrentTokenString);
  695. Result.Kind:=skSingle;
  696. end;
  697. end;
  698. except
  699. MaybeFree(Result,aParent);
  700. Raise;
  701. end;
  702. end;
  703. function TWebIDLParser.ParseInterface(aParent : TIDLBaseObject): TIDLInterfaceDefinition;
  704. (*
  705. On Entry we're on interface. On exit, we're on the } character
  706. *)
  707. Var
  708. tk : TIDLToken;
  709. Attrs : TAttributeList;
  710. M : TIDLDefinition;
  711. isMixin,SemicolonSeen : Boolean;
  712. begin
  713. Attrs:=nil;
  714. ExpectTokens([tkMixin,tkIdentifier]);
  715. isMixin:=CurrentToken=tkMixin;
  716. if CurrentToken=tkMixin then
  717. ExpectToken(tkIdentifier);
  718. Result:=TIDLInterfaceDefinition(Context.Add(aParent,TIDLInterfaceDefinition,CurrentTokenString));
  719. try
  720. Result.IsMixin:=IsMixin;
  721. tk:=GetToken;
  722. if tk=tkColon then
  723. begin
  724. ExpectToken(tkIdentifier);
  725. Result.ParentName:=CurrentTokenString;
  726. tk:=GetToken;
  727. end;
  728. CheckCurrentToken(tkCurlyBraceOpen);
  729. tk:=GetToken;
  730. While (tk<>tkCurlyBraceClose) do
  731. begin
  732. SemicolonSeen:=False;
  733. Attrs:=nil;
  734. M:=Nil;
  735. if tk=tkSquaredBraceOpen then
  736. begin
  737. Attrs:=ParseAttributes;
  738. tk:=GetToken;
  739. end;
  740. Case tk of
  741. tkConst : M:=ParseConst(Result.Members);
  742. tkSetLike : M:=ParseSetLikeMember(Result.Members);
  743. tkMapLike : M:=ParseMapLikeMember(Result.Members);
  744. tkReadOnly :
  745. begin
  746. Case GetToken of
  747. tkAttribute,tkInherit:
  748. begin
  749. M:=ParseAttribute(Result.Members);
  750. With TIDLAttributeDefinition(M) do
  751. Options:=Options+[aoReadOnly];
  752. end;
  753. tkMapLike:
  754. begin
  755. M:=ParseMapLikeMember (Result.Members);
  756. TIDLMapLikeDefinition(M).IsReadonly:=True;
  757. end;
  758. tkSetLike:
  759. begin
  760. M:=ParseSetLikeMember (Result.Members);
  761. TIDLSetLikeDefinition(M).IsReadonly:=True;
  762. end
  763. else
  764. CheckCurrentTokens([tkAttribute,tkInherit,tkMapLike,tkSetLike]);
  765. end;
  766. end;
  767. tkInherit,
  768. tkAttribute : M:=ParseAttribute(Result.Members);
  769. tkStatic : M:=ParseStatic(Result.Members);
  770. tkSerializer :
  771. begin
  772. M:=ParseSerializer(Result.Members);
  773. Result.HasSerializer:=True;
  774. SemicolonSeen:=M=Nil;
  775. end;
  776. tkStringifier : M:=ParseStringifier(Result.Members);
  777. tkIterable : ParseIterable(Result.Members);
  778. else
  779. {
  780. tkGetter, tkSetter, tkDeleter, tkLegacyCaller
  781. }
  782. M:=ParseOperation(Result.Members);
  783. end;
  784. IF Assigned(M) then
  785. begin
  786. M.Attributes:=Attrs;
  787. Attrs:=Nil; // So it does not get freed in except
  788. end;
  789. if not SemicolonSeen then
  790. GetToken;
  791. CheckCurrentToken(tkSemicolon);
  792. tk:=GetToken;
  793. end;
  794. except
  795. FreeAndNil(Attrs);
  796. MaybeFree(Result,aParent);
  797. Raise;
  798. end;
  799. end;
  800. function TWebIDLParser.ParsePartial(aParent : TIDLBaseObject): TIDLStructuredDefinition;
  801. (* On entry, we're on Partial. On exit, we're on the } character *)
  802. begin
  803. Case GetToken of
  804. tkInterface : Result:=ParseInterface(aParent);
  805. tkDictionary : Result:=ParseDictionary(aParent);
  806. else
  807. Error(SErrInvalidTokenList,[GetTokenNames([tkInterface,tkDictionary]),CurrentTokenString]);
  808. end;
  809. Result.IsPartial:=True;
  810. end;
  811. function TWebIDLParser.ParseImplementsOrIncludes(aParent: TIDLBaseObject): TIDLImplementsOrIncludesDefinition;
  812. Var
  813. aName : UTF8String;
  814. begin
  815. aName:=CurrentTokenString;
  816. if version=v1 then
  817. begin
  818. ExpectToken(tkImplements);
  819. Result:=ParseImplements(aName,aParent)
  820. end
  821. else
  822. begin
  823. ExpectTokens([tkImplements,tkIncludes]);
  824. case CurrentToken of
  825. tkIncludes: Result:=ParseIncludes(aName,aParent);
  826. tkImplements: Result:=ParseImplements(aName,aParent);
  827. end;
  828. end;
  829. end;
  830. function TWebIDLParser.ParseEnum(aParent : TIDLBaseObject): TIDLEnumDefinition;
  831. (* On entry, we're on enum. On exit, we're on the } character *)
  832. Var
  833. tk : TIDLToken;
  834. begin
  835. ExpectToken(tkIdentifier);
  836. Result:=TIDLEnumDefinition(Context.Add(aParent,TIDLEnumDefinition,CurrentTokenString));
  837. ExpectToken(tkCurlyBraceOpen);
  838. Repeat
  839. tk:=ExpectTokens([tkCurlyBraceClose,tkString]);
  840. if tk=tkString then
  841. begin
  842. Result.AddValue(CurrentTokenString);
  843. tk:=ExpectTokens([tkCurlyBraceClose,tkComma]);
  844. end;
  845. Until (tk=tkCurlyBraceClose);
  846. end;
  847. function TWebIDLParser.ParseDictionaryMember(aParent : TIDLBaseObject): TIDLDictionaryMemberDefinition;
  848. { On Entry, we're at the start of the member. This may be required, attributes or the type.
  849. On Exit, we're on the ; }
  850. Var
  851. Attrs : TAttributeList;
  852. tk : TIDLToken;
  853. isReq : Boolean;
  854. S : UTF8String;
  855. begin
  856. Attrs:=Nil;
  857. tk:=CurrentToken;
  858. isReq:=(tk=tkRequired);
  859. if IsReq then
  860. tk:=GetToken;
  861. if tk=tkSquaredBraceOpen then
  862. begin
  863. Attrs:=ParseAttributes;
  864. tk:=GetToken;
  865. isReq:=(tk=tkRequired);
  866. if IsReq then
  867. tk:=GetToken;
  868. end;
  869. Result:=TIDLDictionaryMemberDefinition(Context.Add(aParent,TIDLDictionaryMemberDefinition,''));
  870. try
  871. Result.Attributes:=Attrs;
  872. Result.IsRequired:=isReq;
  873. Result.MemberType:=ParseType(Result,False,True);
  874. CheckCurrentToken(tkIdentifier);
  875. Result.Name:=CurrentTokenString;
  876. tk:=GetToken;
  877. if tk=tkEqual then
  878. begin
  879. Result.DefaultValue:=TIDLConstDefinition(Context.Add(Result,TIDLConstDefinition,''));
  880. Result.DefaultValue.ConstType:=ParseConstValue(S,True);
  881. Result.DefaultValue.Value:=S;
  882. tk:=GetToken;
  883. end;
  884. CheckCurrentToken(tkSemicolon);
  885. except
  886. MaybeFree(Result,aParent);
  887. Raise;
  888. end;
  889. end;
  890. function TWebIDLParser.ParseDictionary(aParent : TIDLBaseObject; AllowInheritance : Boolean = True): TIDLDictionaryDefinition;
  891. (* On entry, we're on dictionary, on eexit, we're on { *)
  892. Var
  893. Name,ParentName : UTF8String;
  894. tk : TIDLToken;
  895. begin
  896. ExpectToken(tkIdentifier);
  897. Name:=CurrentTokenString;
  898. tk:=GetToken;
  899. if (tk=tkColon) then
  900. begin
  901. If Not AllowInheritance then
  902. Error(SErrUnExpectedToken,[CurrentTokenString]);
  903. ExpectToken(tkIdentifier);
  904. ParentName:=CurrentTokenString;
  905. tk:=GetToken;
  906. end;
  907. CheckCurrentToken(tkCurlyBraceOpen);
  908. Result:=TIDLDictionaryDefinition(Context.Add(aParent,TIDLDictionaryDefinition,Name));
  909. Result.ParentName:=ParentName;
  910. GetToken;
  911. While (CurrentToken<>tkCurlyBraceClose) do
  912. begin
  913. ParseDictionaryMember(Result.Members);
  914. CheckCurrentTokens([tkSemicolon,tkCurlyBraceClose]);
  915. if (CurrentToken=tkSemicolon) then
  916. GetToken;
  917. end;
  918. end;
  919. function TWebIDLParser.ParseSequenceTypeDef(aParent : TIDLBaseObject): TIDLSequenceTypeDefDefinition;
  920. (* On Entry we're on sequence. On exit, we're on the > token *)
  921. begin
  922. Result:=TIDLSequenceTypeDefDefinition(Context.Add(aParent,TIDLSequenceTypeDefDefinition,''));
  923. try
  924. Result.TypeName:='sequence';
  925. ExpectToken(tkLess);
  926. Result.ElementType:=ParseType(Result);
  927. Result.ElementType.Parent:=Result;
  928. CheckCurrentToken(tkLarger);
  929. except
  930. MaybeFree(Result,aParent);
  931. Raise;
  932. end;
  933. end;
  934. function TWebIDLParser.ParseUnionTypeDef(aParent : TIDLBaseObject): TIDLUnionTypeDefDefinition;
  935. (* On Entry we're on (. On exit, we're on the ) token *)
  936. Var
  937. D : TIDLTypeDefDefinition;
  938. tk : TIDLToken;
  939. Attr : TAttributeList;
  940. begin
  941. Attr:=Nil;
  942. Result:=TIDLUnionTypeDefDefinition(Context.Add(aParent,TIDLUnionTypeDefDefinition,''));
  943. try
  944. Result.TypeName:='union';
  945. Repeat
  946. Attr:=Nil;
  947. tk:=GetToken;
  948. if Tk=tkSquaredBraceOpen then
  949. begin
  950. Attr:=ParseAttributes;
  951. tk:=getToken;
  952. end;
  953. D:=ParseType(Result.Union,False);
  954. D.Attributes:=Attr;
  955. Attr:=Nil;
  956. if (D.TypeName='any') then
  957. Error(SErrTypeNotAllowed,['any','union']);
  958. CheckCurrentTokens([tkOr,tkBracketClose]);
  959. tk:=CurrentToken;
  960. until (tk=tkBracketClose);
  961. except
  962. FreeAndNil(Attr);
  963. MaybeFree(Result,aParent);
  964. Raise;
  965. end;
  966. end;
  967. function TWebIDLParser.ParsePromiseTypeDef(aParent: TIDLBaseObject): TIDLPromiseTypeDefDefinition;
  968. (* On Entry we're on promise. On exit, we're on the > token *)
  969. begin
  970. Result:=TIDLPromiseTypeDefDefinition(Context.Add(aParent,TIDLPromiseTypeDefDefinition,''));
  971. try
  972. Result.TypeName:='Promise';
  973. ExpectToken(tkLess);
  974. Result.ReturnType:=ParseType(Result,True,true);
  975. CheckCurrentToken(tkLarger);
  976. except
  977. MaybeFree(Result,aParent);
  978. Raise;
  979. end;
  980. end;
  981. function TWebIDLParser.ParseType(aParent : TIDLBaseObject; FetchFirst : Boolean = True; AllowExtraTypes : Boolean = False): TIDLTypeDefDefinition;
  982. (* On Entry
  983. if FetchFirst = true we're on "typedef", "(", "or" or "<" tokens.
  984. if FetchFirst = true we're on the first actual token
  985. On exit, we're on the first token after the type
  986. *)
  987. Const
  988. SimplePrefixTokens = [tkUnsigned,tkLong,tkUnrestricted];
  989. ComplexPrefixTokens = [tkSequence,tkPromise,tkBracketOpen,tkRecord,tkFrozenArray];
  990. PrefixTokens = ComplexPrefixTokens+SimplePrefixTokens;
  991. PrimitiveTokens = [tkBoolean,tkByte,tkOctet,tkFloat,tkDouble,tkShort,tkAny,tkObject];
  992. IdentifierTokens = [tkIdentifier,tkByteString,tkUSVString,tkDOMString];
  993. SimpleTypeTokens = PrimitiveTokens+IdentifierTokens;
  994. TypeTokens = PrefixTokens+SimpleTypeTokens;
  995. ExtraTypeTokens = TypeTokens +[tkStringToken,tkVoid];
  996. Var
  997. isNull : Boolean;
  998. typeName: UTF8String;
  999. Allowed : TIDLTokens;
  1000. tk : TIDLToken;
  1001. begin
  1002. if AllowExtraTypes then
  1003. Allowed:=ExtraTypeTokens
  1004. else
  1005. Allowed:=TypeTokens;
  1006. Result:=Nil;
  1007. try
  1008. isNull:=False;
  1009. if FetchFirst then
  1010. tk:=GetToken
  1011. else
  1012. tk:=CurrentToken;
  1013. CheckCurrentTokens(Allowed);
  1014. TypeName:=CurrentTokenString;
  1015. if (tk in SimplePrefixTokens) then
  1016. begin
  1017. tk:=CompleteSimpleType(tk,TypeName,isNull);
  1018. Result:=TIDLTypeDefDefinition(Context.Add(aParent,TIDLTypeDefDefinition,''));
  1019. end
  1020. else
  1021. begin
  1022. Case tk of
  1023. tkRecord : Result:=ParseRecordTypeDef(aParent);
  1024. tkFrozenArray,
  1025. tkSequence : Result:=ParseSequenceTypeDef(aParent);
  1026. tkPromise : Result:=ParsePromiseTypeDef(aParent);
  1027. tkBracketOpen : Result:=ParseUnionTypeDef(aParent);
  1028. else
  1029. Result:=TIDLTypeDefDefinition(Context.Add(aParent,TIDLTypeDefDefinition,''));
  1030. end;
  1031. tk:=GetToken;
  1032. end;
  1033. if Result.TypeName='' then
  1034. Result.TypeName:=TypeName;
  1035. // Null ?
  1036. if tk=tkQuestionmark then
  1037. begin
  1038. tk:=GetToken;
  1039. isNull:=True;
  1040. end;
  1041. if Assigned(Result) then
  1042. Result.AllowNull:=isNull;
  1043. Except
  1044. MaybeFree(Result,aParent);
  1045. Raise;
  1046. end;
  1047. end;
  1048. function TWebIDLParser.ParseTypeDef(aParent : TIDLBaseObject): TIDLTypeDefDefinition;
  1049. (* On Entry we're on "typedef", "or" or "<" tokens. On exit, we're on the identifier *)
  1050. begin
  1051. Result:=ParseType(aParent);
  1052. try
  1053. CheckCurrentToken(tkIdentifier);
  1054. Result.Name:=CurrentTokenString;
  1055. Except
  1056. MaybeFree(Result,aParent);
  1057. Raise;
  1058. end;
  1059. end;
  1060. function TWebIDLParser.ParseImplements(const aName: UTF8String;
  1061. aParent: TIDLBaseObject): TIDLImplementsDefinition;
  1062. (* On entry, we're on the identifier for V1, we're. On Exit, we're on the last identifier *)
  1063. Var
  1064. N : UTF8String;
  1065. begin
  1066. if Version=V1 then
  1067. begin
  1068. N:=aName
  1069. end
  1070. else
  1071. N:=aName;
  1072. Result:=TIDLImplementsDefinition(Context.Add(aParent,TIDLImplementsDefinition,N));
  1073. try
  1074. ExpectToken(tkIdentifier);
  1075. Result.ImplementedInterface:=CurrentTokenString;
  1076. except
  1077. MaybeFree(Result,aParent);
  1078. end;
  1079. end;
  1080. function TWebIDLParser.ParseIncludes(const aName: UTF8String;
  1081. aParent: TIDLBaseObject): TIDLIncludesDefinition;
  1082. (* On entry, we're on the identifier. On Exit, we're on the last identifier *)
  1083. begin
  1084. Result:=TIDLIncludesDefinition(Context.Add(aParent,TIDLIncludesDefinition,aName));
  1085. try
  1086. ExpectToken(tkIdentifier);
  1087. Result.IncludedInterface:=CurrentTokenString;
  1088. except
  1089. MaybeFree(Result,aParent);
  1090. end;
  1091. end;
  1092. function TWebIDLParser.ParseDefinition(aParent : TIDLBaseObject): TIDLDefinition;
  1093. Var
  1094. tk : TIDLToken;
  1095. Attrs : TAttributeList;
  1096. begin
  1097. Result:=Nil;
  1098. Attrs:=Nil;
  1099. tk:=GetToken;
  1100. if tk=tkSquaredBraceOpen then
  1101. begin
  1102. Attrs:=ParseAttributes;
  1103. tk:=GetToken;
  1104. end;
  1105. Try
  1106. Case tk of
  1107. tkCallback : Result:=ParseCallBack(aParent);
  1108. tkInterface : Result:=ParseInterface(aParent);
  1109. tkDictionary : Result:=ParseDictionary(aParent);
  1110. tkPartial : Result:=ParsePartial(aParent);
  1111. tkEnum : Result:=ParseEnum(aParent);
  1112. tkTypeDef : Result:=ParseTypeDef(aParent);
  1113. tkIdentifier :
  1114. Result:=ParseImplementsOrIncludes(aParent);
  1115. tkEOF : exit;
  1116. else
  1117. Error(SErrUnExpectedToken,[CurrentTokenString]);
  1118. end;
  1119. if Assigned(Result) then
  1120. begin
  1121. Result.Attributes:=Attrs;
  1122. Attrs:=nil;
  1123. end;
  1124. except
  1125. FreeAndNil(Attrs);
  1126. Raise;
  1127. end;
  1128. ExpectToken(tkSemicolon);
  1129. end;
  1130. procedure TWebIDLParser.ParseDefinitions(aParent : TIDLBaseObject);
  1131. begin
  1132. Repeat
  1133. ParseDefinition(aParent);
  1134. Until (CurrentToken=tkEOF)
  1135. end;
  1136. procedure TWebIDLParser.Parse;
  1137. begin
  1138. ParseDefinitions(Context.Definitions);
  1139. end;
  1140. { TWebIDLContext }
  1141. constructor TWebIDLContext.Create(OwnsDefinitions : Boolean = True);
  1142. begin
  1143. FDefinitions:=TIDLDefinitionList.Create(Nil,OwnsDefinitions);
  1144. end;
  1145. destructor TWebIDLContext.Destroy;
  1146. begin
  1147. FreeAndNil(FDefinitions);
  1148. FreeAndNil(FHash);
  1149. inherited Destroy;
  1150. end;
  1151. function TWebIDLContext.FindDictionary(aName: UTF8String
  1152. ): TIDLDictionaryDefinition;
  1153. Var
  1154. I : Integer;
  1155. begin
  1156. I:=0;
  1157. Result:=Nil;
  1158. While (Result=Nil) and (I<FDefinitions.Count) do
  1159. begin
  1160. if (FDefinitions[i] is TIDLDictionaryDefinition) then
  1161. begin
  1162. Result:=TIDLDictionaryDefinition(FDefinitions[i]);
  1163. if (Result.Name<>aName) or (Result.IsPartial) then
  1164. Result:=nil;
  1165. end;
  1166. Inc(I);
  1167. end;
  1168. end;
  1169. function TWebIDLContext.FindInterface(aName: UTF8String
  1170. ): TIDLInterfaceDefinition;
  1171. Var
  1172. I : Integer;
  1173. begin
  1174. I:=0;
  1175. Result:=Nil;
  1176. While (Result=Nil) and (I<FDefinitions.Count) do
  1177. begin
  1178. if (FDefinitions[i] is TIDLInterfaceDefinition) then
  1179. begin
  1180. Result:=TIDLInterfaceDefinition(FDefinitions[i]);
  1181. if (Result.Name<>aName) or (Result.IsPartial) then
  1182. Result:=nil;
  1183. end;
  1184. Inc(I);
  1185. end;
  1186. end;
  1187. procedure TWebIDLContext.AppendDictionaryPartials;
  1188. Var
  1189. D : TIDLDefinition;
  1190. DD : TIDLDictionaryDefinition absolute D;
  1191. OD : TIDLDictionaryDefinition;
  1192. begin
  1193. For D in FDefinitions do
  1194. if (D is TIDLDictionaryDefinition) and (DD.IsPartial) then
  1195. begin
  1196. OD:=FindDictionary(DD.Name);
  1197. If (OD=Nil) then
  1198. Raise EWebIDLParser.CreateFmt(SErrDictionaryNotFound,[DD.Name]);
  1199. OD.Partials.Add(DD);
  1200. end;
  1201. end;
  1202. procedure TWebIDLContext.AppendInterfacePartials;
  1203. Var
  1204. D : TIDLDefinition;
  1205. ID : TIDLInterfaceDefinition absolute D;
  1206. OD : TIDLInterfaceDefinition;
  1207. begin
  1208. For D in FDefinitions do
  1209. if (D is TIDLInterfaceDefinition) and (ID.IsPartial) then
  1210. begin
  1211. OD:=FindInterface(ID.Name);
  1212. If (OD<>Nil) then
  1213. OD.Partials.Add(ID);
  1214. end;
  1215. end;
  1216. procedure TWebIDLContext.AppendInterfaceIncludes;
  1217. Var
  1218. D : TIDLDefinition;
  1219. ID : TIDLIncludesDefinition absolute D;
  1220. II,OI : TIDLInterfaceDefinition; // Includes and original
  1221. begin
  1222. For D in FDefinitions do
  1223. if (D is TIDLIncludesDefinition) then
  1224. begin
  1225. OI:=FindInterface(ID.Name);
  1226. If (OI=Nil) then
  1227. Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFound,[ID.Name]);
  1228. II:=FindInterface(ID.IncludedInterface);
  1229. If (II=Nil) then
  1230. begin
  1231. if Assigned(Aliases) and (Aliases.IndexOfName(ID.IncludedInterface)<>-1) then
  1232. OI.ParentName:=Aliases.Values[ID.IncludedInterface]
  1233. else
  1234. Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFoundFor,[ID.IncludedInterface,ID.Name]);
  1235. end
  1236. else
  1237. begin
  1238. II.IsInclude:=True;
  1239. OI.Partials.Add(II);
  1240. end
  1241. end;
  1242. // if there is a single include, no members and no parent, make it a descendent
  1243. For D in FDefinitions do
  1244. if (D is TIDLInterfaceDefinition) then
  1245. begin
  1246. OI:=D as TIDLInterfaceDefinition;
  1247. if (OI.ParentName='') and (OI.Partials.Count=1) then
  1248. if (OI.Partial[0] is TIDLInterfaceDefinition) then
  1249. begin
  1250. II:=OI.Partial[0] as TIDLInterfaceDefinition;
  1251. if II.IsInclude then
  1252. begin
  1253. // DoLog('Converting single include %s to parent class for %s',[II.Name,OI.Name]);
  1254. OI.ParentName:=II.Name;
  1255. OI.ParentInterface:=II;
  1256. OI.Partials.Clear;
  1257. end;
  1258. end;
  1259. end;
  1260. end;
  1261. procedure TWebIDLContext.AppendPartials;
  1262. begin
  1263. AppendDictionaryPartials;
  1264. AppendInterfacePartials;
  1265. end;
  1266. procedure TWebIDLContext.AppendIncludes;
  1267. begin
  1268. AppendInterfaceIncludes;
  1269. end;
  1270. procedure TWebIDLContext.ResolveParentTypes;
  1271. Var
  1272. D : TIDLDefinition;
  1273. ID : TIDLInterfaceDefinition absolute D;
  1274. DD : TIDLDictionaryDefinition absolute D;
  1275. begin
  1276. For D in FDefinitions do
  1277. if D is TIDLInterfaceDefinition then
  1278. begin
  1279. if (ID.ParentName<>'') then
  1280. ID.ParentInterface:=FindInterface(ID.ParentName);
  1281. end
  1282. else if D is TIDLDictionaryDefinition then
  1283. if (DD.ParentName<>'') then
  1284. DD.ParentDictionary:=FindDictionary(DD.ParentName);
  1285. end;
  1286. procedure TWebIDLContext.ResolveTypes;
  1287. begin
  1288. ResolveParentTypes;
  1289. end;
  1290. function TWebIDLContext.IndexOfDefinition(const AName: String): Integer;
  1291. begin
  1292. Result:=Definitions.Count-1;
  1293. While (Result>=0) and (Definitions[Result].Name<>AName) do
  1294. Dec(Result);
  1295. end;
  1296. function TWebIDLContext.FindDefinition(const AName: String): TIDLDefinition;
  1297. Var
  1298. D : TIDLDefinition;
  1299. begin
  1300. if (FHash=Nil) then
  1301. begin
  1302. FHash:=TFPObjectHashTable.Create(False);
  1303. For D in Definitions do
  1304. if not D.IsExtension then
  1305. FHash.Add(D.Name,D);
  1306. end;
  1307. Result:=TIDLDefinition(FHash.Items[AName]);
  1308. end;
  1309. function TWebIDLContext.AsString(Full: Boolean): UTF8String;
  1310. begin
  1311. Result:=Definitions.AsString(';'+sLineBreak,'','','',True,True);
  1312. end;
  1313. function TWebIDLContext.Add(aClass: TIDLDefinitionClass; const AName: UTF8String): TIDLDefinition;
  1314. begin
  1315. Result:=Add(FDefinitions,aClass,AName);
  1316. end;
  1317. function TWebIDLContext.Add(aParent: TIDLBaseObject; aClass: TIDLDefinitionClass; const AName: UTF8String): TIDLDefinition;
  1318. begin
  1319. if Assigned(aParent) then
  1320. Result:=aParent.Add(aClass,aName)
  1321. else
  1322. Result:=aClass.Create(Nil,aName)
  1323. end;
  1324. end.