IDLParser.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
  5. * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include "IDLParser.h"
  10. #include <AK/LexicalPath.h>
  11. #include <AK/QuickSort.h>
  12. #include <LibCore/File.h>
  13. [[noreturn]] static void report_parsing_error(StringView message, StringView filename, StringView input, size_t offset)
  14. {
  15. // FIXME: Spaghetti code ahead.
  16. size_t lineno = 1;
  17. size_t colno = 1;
  18. size_t start_line = 0;
  19. size_t line_length = 0;
  20. for (size_t index = 0; index < input.length(); ++index) {
  21. if (offset == index)
  22. colno = index - start_line + 1;
  23. if (input[index] == '\n') {
  24. if (index >= offset)
  25. break;
  26. start_line = index + 1;
  27. line_length = 0;
  28. ++lineno;
  29. } else {
  30. ++line_length;
  31. }
  32. }
  33. StringBuilder error_message;
  34. error_message.appendff("{}\n", input.substring_view(start_line, line_length));
  35. for (size_t i = 0; i < colno - 1; ++i)
  36. error_message.append(' ');
  37. error_message.append("\033[1;31m^\n");
  38. error_message.appendff("{}:{}: error: {}\033[0m\n", filename, lineno, message);
  39. warnln("{}", error_message.string_view());
  40. exit(EXIT_FAILURE);
  41. }
  42. static String convert_enumeration_value_to_cpp_enum_member(String const& value, HashTable<String>& names_already_seen)
  43. {
  44. StringBuilder builder;
  45. GenericLexer lexer { value };
  46. while (!lexer.is_eof()) {
  47. lexer.ignore_while([](auto c) { return is_ascii_space(c) || c == '-' || c == '_'; });
  48. auto word = lexer.consume_while([](auto c) { return is_ascii_alphanumeric(c); });
  49. if (!word.is_empty()) {
  50. builder.append(word.to_titlecase_string());
  51. } else {
  52. auto non_alnum_string = lexer.consume_while([](auto c) { return !is_ascii_alphanumeric(c); });
  53. if (!non_alnum_string.is_empty())
  54. builder.append("_");
  55. }
  56. }
  57. if (builder.is_empty())
  58. builder.append("Empty");
  59. while (names_already_seen.contains(builder.string_view()))
  60. builder.append('_');
  61. names_already_seen.set(builder.string_view());
  62. return builder.build();
  63. }
  64. namespace IDL {
  65. HashMap<String, NonnullRefPtr<Interface>> Parser::s_resolved_imports {};
  66. void Parser::assert_specific(char ch)
  67. {
  68. if (!lexer.consume_specific(ch))
  69. report_parsing_error(String::formatted("expected '{}'", ch), filename, input, lexer.tell());
  70. }
  71. void Parser::consume_whitespace()
  72. {
  73. bool consumed = true;
  74. while (consumed) {
  75. consumed = lexer.consume_while(is_ascii_space).length() > 0;
  76. if (lexer.consume_specific("//")) {
  77. lexer.consume_until('\n');
  78. lexer.ignore();
  79. consumed = true;
  80. }
  81. }
  82. }
  83. void Parser::assert_string(StringView expected)
  84. {
  85. if (!lexer.consume_specific(expected))
  86. report_parsing_error(String::formatted("expected '{}'", expected), filename, input, lexer.tell());
  87. }
  88. HashMap<String, String> Parser::parse_extended_attributes()
  89. {
  90. HashMap<String, String> extended_attributes;
  91. for (;;) {
  92. consume_whitespace();
  93. if (lexer.consume_specific(']'))
  94. break;
  95. auto name = lexer.consume_until([](auto ch) { return ch == ']' || ch == '=' || ch == ','; });
  96. if (lexer.consume_specific('=')) {
  97. auto value = lexer.consume_until([](auto ch) { return ch == ']' || ch == ','; });
  98. extended_attributes.set(name, value);
  99. } else {
  100. extended_attributes.set(name, {});
  101. }
  102. lexer.consume_specific(',');
  103. }
  104. consume_whitespace();
  105. return extended_attributes;
  106. }
  107. static HashTable<String> import_stack;
  108. Optional<NonnullRefPtr<Interface>> Parser::resolve_import(auto path)
  109. {
  110. auto include_path = LexicalPath::join(import_base_path, path).string();
  111. if (!Core::File::exists(include_path))
  112. report_parsing_error(String::formatted("{}: No such file or directory", include_path), filename, input, lexer.tell());
  113. auto real_path = Core::File::real_path_for(include_path);
  114. if (s_resolved_imports.contains(real_path))
  115. return s_resolved_imports.find(real_path)->value;
  116. if (import_stack.contains(real_path))
  117. report_parsing_error(String::formatted("Circular import detected: {}", include_path), filename, input, lexer.tell());
  118. import_stack.set(real_path);
  119. auto file_or_error = Core::File::open(real_path, Core::OpenMode::ReadOnly);
  120. if (file_or_error.is_error())
  121. report_parsing_error(String::formatted("Failed to open {}: {}", real_path, file_or_error.error()), filename, input, lexer.tell());
  122. auto data = file_or_error.value()->read_all();
  123. auto result = Parser(real_path, data, import_base_path).parse();
  124. import_stack.remove(real_path);
  125. s_resolved_imports.set(real_path, result);
  126. return result;
  127. }
  128. NonnullRefPtr<Type> Parser::parse_type()
  129. {
  130. if (lexer.consume_specific('(')) {
  131. NonnullRefPtrVector<Type> union_member_types;
  132. union_member_types.append(parse_type());
  133. consume_whitespace();
  134. assert_string("or");
  135. consume_whitespace();
  136. union_member_types.append(parse_type());
  137. consume_whitespace();
  138. while (lexer.consume_specific("or")) {
  139. consume_whitespace();
  140. union_member_types.append(parse_type());
  141. consume_whitespace();
  142. }
  143. assert_specific(')');
  144. bool nullable = lexer.consume_specific('?');
  145. return adopt_ref(*new UnionType("", nullable, move(union_member_types)));
  146. }
  147. bool unsigned_ = lexer.consume_specific("unsigned");
  148. if (unsigned_)
  149. consume_whitespace();
  150. auto name = lexer.consume_until([](auto ch) { return !is_ascii_alphanumeric(ch) && ch != '_'; });
  151. NonnullRefPtrVector<Type> parameters;
  152. bool is_parameterized_type = false;
  153. if (lexer.consume_specific('<')) {
  154. is_parameterized_type = true;
  155. parameters.append(parse_type());
  156. while (lexer.consume_specific(',')) {
  157. consume_whitespace();
  158. parameters.append(parse_type());
  159. }
  160. lexer.consume_specific('>');
  161. }
  162. auto nullable = lexer.consume_specific('?');
  163. StringBuilder builder;
  164. if (unsigned_)
  165. builder.append("unsigned ");
  166. builder.append(name);
  167. if (is_parameterized_type)
  168. return adopt_ref(*new ParameterizedType(builder.to_string(), nullable, move(parameters)));
  169. return adopt_ref(*new Type(builder.to_string(), nullable));
  170. }
  171. void Parser::parse_attribute(HashMap<String, String>& extended_attributes, Interface& interface)
  172. {
  173. bool readonly = lexer.consume_specific("readonly");
  174. if (readonly)
  175. consume_whitespace();
  176. if (lexer.consume_specific("attribute"))
  177. consume_whitespace();
  178. auto type = parse_type();
  179. consume_whitespace();
  180. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; });
  181. consume_whitespace();
  182. assert_specific(';');
  183. auto name_as_string = name.to_string();
  184. auto getter_callback_name = String::formatted("{}_getter", name_as_string.to_snakecase());
  185. auto setter_callback_name = String::formatted("{}_setter", name_as_string.to_snakecase());
  186. Attribute attribute {
  187. readonly,
  188. move(type),
  189. move(name_as_string),
  190. move(extended_attributes),
  191. move(getter_callback_name),
  192. move(setter_callback_name),
  193. };
  194. interface.attributes.append(move(attribute));
  195. }
  196. void Parser::parse_constant(Interface& interface)
  197. {
  198. lexer.consume_specific("const");
  199. consume_whitespace();
  200. auto type = parse_type();
  201. consume_whitespace();
  202. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == '='; });
  203. consume_whitespace();
  204. lexer.consume_specific('=');
  205. consume_whitespace();
  206. auto value = lexer.consume_while([](auto ch) { return !is_ascii_space(ch) && ch != ';'; });
  207. consume_whitespace();
  208. assert_specific(';');
  209. Constant constant {
  210. move(type),
  211. move(name),
  212. move(value),
  213. };
  214. interface.constants.append(move(constant));
  215. }
  216. Vector<Parameter> Parser::parse_parameters()
  217. {
  218. consume_whitespace();
  219. Vector<Parameter> parameters;
  220. for (;;) {
  221. if (lexer.next_is(')'))
  222. break;
  223. HashMap<String, String> extended_attributes;
  224. if (lexer.consume_specific('['))
  225. extended_attributes = parse_extended_attributes();
  226. bool optional = lexer.consume_specific("optional");
  227. if (optional)
  228. consume_whitespace();
  229. auto type = parse_type();
  230. bool variadic = lexer.consume_specific("..."sv);
  231. consume_whitespace();
  232. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ',' || ch == ')' || ch == '='; });
  233. Parameter parameter = { move(type), move(name), optional, {}, extended_attributes, variadic };
  234. consume_whitespace();
  235. if (variadic) {
  236. // Variadic parameters must be last and do not have default values.
  237. parameters.append(move(parameter));
  238. break;
  239. }
  240. if (lexer.next_is(')')) {
  241. parameters.append(move(parameter));
  242. break;
  243. }
  244. if (lexer.next_is('=') && optional) {
  245. assert_specific('=');
  246. consume_whitespace();
  247. auto default_value = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ',' || ch == ')'; });
  248. parameter.optional_default_value = default_value;
  249. }
  250. parameters.append(move(parameter));
  251. if (lexer.next_is(')'))
  252. break;
  253. assert_specific(',');
  254. consume_whitespace();
  255. }
  256. return parameters;
  257. }
  258. Function Parser::parse_function(HashMap<String, String>& extended_attributes, Interface& interface, IsSpecialOperation is_special_operation)
  259. {
  260. bool static_ = false;
  261. if (lexer.consume_specific("static")) {
  262. static_ = true;
  263. consume_whitespace();
  264. }
  265. auto return_type = parse_type();
  266. consume_whitespace();
  267. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == '('; });
  268. consume_whitespace();
  269. assert_specific('(');
  270. auto parameters = parse_parameters();
  271. assert_specific(')');
  272. consume_whitespace();
  273. assert_specific(';');
  274. Function function { move(return_type), name, move(parameters), move(extended_attributes), {}, false };
  275. // "Defining a special operation with an identifier is equivalent to separating the special operation out into its own declaration without an identifier."
  276. if (is_special_operation == IsSpecialOperation::No || (is_special_operation == IsSpecialOperation::Yes && !name.is_empty())) {
  277. if (!static_)
  278. interface.functions.append(function);
  279. else
  280. interface.static_functions.append(function);
  281. }
  282. return function;
  283. }
  284. void Parser::parse_constructor(Interface& interface)
  285. {
  286. assert_string("constructor");
  287. consume_whitespace();
  288. assert_specific('(');
  289. auto parameters = parse_parameters();
  290. assert_specific(')');
  291. consume_whitespace();
  292. assert_specific(';');
  293. interface.constructors.append(Constructor { interface.name, move(parameters) });
  294. }
  295. void Parser::parse_stringifier(HashMap<String, String>& extended_attributes, Interface& interface)
  296. {
  297. assert_string("stringifier");
  298. consume_whitespace();
  299. interface.has_stringifier = true;
  300. if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
  301. parse_attribute(extended_attributes, interface);
  302. interface.stringifier_attribute = interface.attributes.last().name;
  303. } else {
  304. assert_specific(';');
  305. }
  306. }
  307. void Parser::parse_iterable(Interface& interface)
  308. {
  309. assert_string("iterable");
  310. assert_specific('<');
  311. auto first_type = parse_type();
  312. if (lexer.next_is(',')) {
  313. if (interface.supports_indexed_properties())
  314. report_parsing_error("Interfaces with a pair iterator must not supported indexed properties.", filename, input, lexer.tell());
  315. assert_specific(',');
  316. consume_whitespace();
  317. auto second_type = parse_type();
  318. interface.pair_iterator_types = Tuple { move(first_type), move(second_type) };
  319. } else {
  320. if (!interface.supports_indexed_properties())
  321. report_parsing_error("Interfaces with a value iterator must supported indexed properties.", filename, input, lexer.tell());
  322. interface.value_iterator_type = move(first_type);
  323. }
  324. assert_specific('>');
  325. assert_specific(';');
  326. }
  327. void Parser::parse_getter(HashMap<String, String>& extended_attributes, Interface& interface)
  328. {
  329. assert_string("getter");
  330. consume_whitespace();
  331. auto function = parse_function(extended_attributes, interface, IsSpecialOperation::Yes);
  332. if (function.parameters.size() != 1)
  333. report_parsing_error(String::formatted("Named/indexed property getters must have only 1 parameter, got {} parameters.", function.parameters.size()), filename, input, lexer.tell());
  334. auto& identifier = function.parameters.first();
  335. if (identifier.type->nullable)
  336. report_parsing_error("identifier's type must not be nullable.", filename, input, lexer.tell());
  337. if (identifier.optional)
  338. report_parsing_error("identifier must not be optional.", filename, input, lexer.tell());
  339. // FIXME: Disallow variadic functions once they're supported.
  340. if (identifier.type->name == "DOMString") {
  341. if (interface.named_property_getter.has_value())
  342. report_parsing_error("An interface can only have one named property getter.", filename, input, lexer.tell());
  343. interface.named_property_getter = move(function);
  344. } else if (identifier.type->name == "unsigned long") {
  345. if (interface.indexed_property_getter.has_value())
  346. report_parsing_error("An interface can only have one indexed property getter.", filename, input, lexer.tell());
  347. interface.indexed_property_getter = move(function);
  348. } else {
  349. report_parsing_error(String::formatted("Named/indexed property getter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name), filename, input, lexer.tell());
  350. }
  351. }
  352. void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interface& interface)
  353. {
  354. assert_string("setter");
  355. consume_whitespace();
  356. auto function = parse_function(extended_attributes, interface, IsSpecialOperation::Yes);
  357. if (function.parameters.size() != 2)
  358. report_parsing_error(String::formatted("Named/indexed property setters must have only 2 parameters, got {} parameter(s).", function.parameters.size()), filename, input, lexer.tell());
  359. auto& identifier = function.parameters.first();
  360. if (identifier.type->nullable)
  361. report_parsing_error("identifier's type must not be nullable.", filename, input, lexer.tell());
  362. if (identifier.optional)
  363. report_parsing_error("identifier must not be optional.", filename, input, lexer.tell());
  364. // FIXME: Disallow variadic functions once they're supported.
  365. if (identifier.type->name == "DOMString") {
  366. if (interface.named_property_setter.has_value())
  367. report_parsing_error("An interface can only have one named property setter.", filename, input, lexer.tell());
  368. if (!interface.named_property_getter.has_value())
  369. report_parsing_error("A named property setter must be accompanied by a named property getter.", filename, input, lexer.tell());
  370. interface.named_property_setter = move(function);
  371. } else if (identifier.type->name == "unsigned long") {
  372. if (interface.indexed_property_setter.has_value())
  373. report_parsing_error("An interface can only have one indexed property setter.", filename, input, lexer.tell());
  374. if (!interface.indexed_property_getter.has_value())
  375. report_parsing_error("An indexed property setter must be accompanied by an indexed property getter.", filename, input, lexer.tell());
  376. interface.indexed_property_setter = move(function);
  377. } else {
  378. report_parsing_error(String::formatted("Named/indexed property setter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name), filename, input, lexer.tell());
  379. }
  380. }
  381. void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interface& interface)
  382. {
  383. assert_string("deleter");
  384. consume_whitespace();
  385. auto function = parse_function(extended_attributes, interface, IsSpecialOperation::Yes);
  386. if (function.parameters.size() != 1)
  387. report_parsing_error(String::formatted("Named property deleter must have only 1 parameter, got {} parameters.", function.parameters.size()), filename, input, lexer.tell());
  388. auto& identifier = function.parameters.first();
  389. if (identifier.type->nullable)
  390. report_parsing_error("identifier's type must not be nullable.", filename, input, lexer.tell());
  391. if (identifier.optional)
  392. report_parsing_error("identifier must not be optional.", filename, input, lexer.tell());
  393. // FIXME: Disallow variadic functions once they're supported.
  394. if (identifier.type->name == "DOMString") {
  395. if (interface.named_property_deleter.has_value())
  396. report_parsing_error("An interface can only have one named property deleter.", filename, input, lexer.tell());
  397. if (!interface.named_property_getter.has_value())
  398. report_parsing_error("A named property deleter must be accompanied by a named property getter.", filename, input, lexer.tell());
  399. interface.named_property_deleter = move(function);
  400. } else {
  401. report_parsing_error(String::formatted("Named property deleter's identifier's type must be 'DOMString', got '{}'.", identifier.type->name), filename, input, lexer.tell());
  402. }
  403. }
  404. void Parser::parse_interface(Interface& interface)
  405. {
  406. consume_whitespace();
  407. interface.name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  408. consume_whitespace();
  409. if (lexer.consume_specific(':')) {
  410. consume_whitespace();
  411. interface.parent_name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  412. consume_whitespace();
  413. }
  414. assert_specific('{');
  415. for (;;) {
  416. HashMap<String, String> extended_attributes;
  417. consume_whitespace();
  418. if (lexer.consume_specific('}')) {
  419. consume_whitespace();
  420. assert_specific(';');
  421. break;
  422. }
  423. if (lexer.consume_specific('[')) {
  424. extended_attributes = parse_extended_attributes();
  425. if (!interface.has_unscopable_member && extended_attributes.contains("Unscopable"))
  426. interface.has_unscopable_member = true;
  427. }
  428. if (lexer.next_is("constructor")) {
  429. parse_constructor(interface);
  430. continue;
  431. }
  432. if (lexer.next_is("const")) {
  433. parse_constant(interface);
  434. continue;
  435. }
  436. if (lexer.next_is("stringifier")) {
  437. parse_stringifier(extended_attributes, interface);
  438. continue;
  439. }
  440. if (lexer.next_is("iterable")) {
  441. parse_iterable(interface);
  442. continue;
  443. }
  444. if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
  445. parse_attribute(extended_attributes, interface);
  446. continue;
  447. }
  448. if (lexer.next_is("getter")) {
  449. parse_getter(extended_attributes, interface);
  450. continue;
  451. }
  452. if (lexer.next_is("setter")) {
  453. parse_setter(extended_attributes, interface);
  454. continue;
  455. }
  456. if (lexer.next_is("deleter")) {
  457. parse_deleter(extended_attributes, interface);
  458. continue;
  459. }
  460. parse_function(extended_attributes, interface);
  461. }
  462. interface.wrapper_class = String::formatted("{}Wrapper", interface.name);
  463. interface.wrapper_base_class = String::formatted("{}Wrapper", interface.parent_name.is_empty() ? String::empty() : interface.parent_name);
  464. interface.constructor_class = String::formatted("{}Constructor", interface.name);
  465. interface.prototype_class = String::formatted("{}Prototype", interface.name);
  466. interface.prototype_base_class = String::formatted("{}Prototype", interface.parent_name.is_empty() ? "Object" : interface.parent_name);
  467. consume_whitespace();
  468. }
  469. void Parser::parse_enumeration(Interface& interface)
  470. {
  471. assert_string("enum");
  472. consume_whitespace();
  473. Enumeration enumeration {};
  474. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  475. consume_whitespace();
  476. assert_specific('{');
  477. bool first = true;
  478. for (; !lexer.is_eof();) {
  479. consume_whitespace();
  480. if (lexer.next_is('}'))
  481. break;
  482. if (!first) {
  483. assert_specific(',');
  484. consume_whitespace();
  485. }
  486. assert_specific('"');
  487. auto string = lexer.consume_until('"');
  488. assert_specific('"');
  489. consume_whitespace();
  490. if (enumeration.values.contains(string))
  491. report_parsing_error(String::formatted("Enumeration {} contains duplicate member '{}'", name, string), filename, input, lexer.tell());
  492. else
  493. enumeration.values.set(string);
  494. if (first)
  495. enumeration.first_member = move(string);
  496. first = false;
  497. }
  498. consume_whitespace();
  499. assert_specific('}');
  500. assert_specific(';');
  501. HashTable<String> names_already_seen;
  502. for (auto& entry : enumeration.values)
  503. enumeration.translated_cpp_names.set(entry, convert_enumeration_value_to_cpp_enum_member(entry, names_already_seen));
  504. interface.enumerations.set(name, move(enumeration));
  505. consume_whitespace();
  506. }
  507. void Parser::parse_typedef(Interface& interface)
  508. {
  509. assert_string("typedef");
  510. consume_whitespace();
  511. HashMap<String, String> extended_attributes;
  512. if (lexer.consume_specific('['))
  513. extended_attributes = parse_extended_attributes();
  514. auto type = parse_type();
  515. consume_whitespace();
  516. auto name = lexer.consume_until(';');
  517. assert_specific(';');
  518. interface.typedefs.set(name, Typedef { move(extended_attributes), move(type) });
  519. consume_whitespace();
  520. }
  521. void Parser::parse_dictionary(Interface& interface)
  522. {
  523. assert_string("dictionary");
  524. consume_whitespace();
  525. Dictionary dictionary {};
  526. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  527. consume_whitespace();
  528. if (lexer.consume_specific(':')) {
  529. consume_whitespace();
  530. dictionary.parent_name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  531. consume_whitespace();
  532. }
  533. assert_specific('{');
  534. for (;;) {
  535. consume_whitespace();
  536. if (lexer.consume_specific('}')) {
  537. consume_whitespace();
  538. assert_specific(';');
  539. break;
  540. }
  541. bool required = false;
  542. HashMap<String, String> extended_attributes;
  543. if (lexer.consume_specific("required")) {
  544. required = true;
  545. consume_whitespace();
  546. if (lexer.consume_specific('['))
  547. extended_attributes = parse_extended_attributes();
  548. }
  549. auto type = parse_type();
  550. consume_whitespace();
  551. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; });
  552. consume_whitespace();
  553. Optional<StringView> default_value;
  554. if (lexer.consume_specific('=')) {
  555. VERIFY(!required);
  556. consume_whitespace();
  557. default_value = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; });
  558. consume_whitespace();
  559. }
  560. assert_specific(';');
  561. DictionaryMember member {
  562. required,
  563. move(type),
  564. name,
  565. move(extended_attributes),
  566. Optional<String>(move(default_value)),
  567. };
  568. dictionary.members.append(move(member));
  569. }
  570. // dictionary members need to be evaluated in lexicographical order
  571. quick_sort(dictionary.members, [&](auto& one, auto& two) {
  572. return one.name < two.name;
  573. });
  574. interface.dictionaries.set(name, move(dictionary));
  575. consume_whitespace();
  576. }
  577. void Parser::parse_interface_mixin(Interface& interface)
  578. {
  579. auto mixin_interface = make_ref_counted<Interface>();
  580. mixin_interface->module_own_path = interface.module_own_path;
  581. mixin_interface->is_mixin = true;
  582. assert_string("interface");
  583. consume_whitespace();
  584. assert_string("mixin");
  585. auto offset = lexer.tell();
  586. parse_interface(*mixin_interface);
  587. if (!mixin_interface->parent_name.is_empty())
  588. report_parsing_error("Mixin interfaces are not allowed to have inherited parents", filename, input, offset);
  589. auto name = mixin_interface->name;
  590. interface.mixins.set(move(name), move(mixin_interface));
  591. }
  592. void Parser::parse_callback_function(HashMap<String, String>& extended_attributes, Interface& interface)
  593. {
  594. assert_string("callback");
  595. consume_whitespace();
  596. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  597. consume_whitespace();
  598. assert_specific('=');
  599. consume_whitespace();
  600. auto return_type = parse_type();
  601. consume_whitespace();
  602. assert_specific('(');
  603. auto parameters = parse_parameters();
  604. assert_specific(')');
  605. consume_whitespace();
  606. assert_specific(';');
  607. interface.callback_functions.set(name, CallbackFunction { move(return_type), move(parameters), extended_attributes.contains("LegacyTreatNonObjectAsNull") });
  608. consume_whitespace();
  609. }
  610. void Parser::parse_non_interface_entities(bool allow_interface, Interface& interface)
  611. {
  612. while (!lexer.is_eof()) {
  613. HashMap<String, String> extended_attributes;
  614. if (lexer.consume_specific('['))
  615. extended_attributes = parse_extended_attributes();
  616. if (lexer.next_is("dictionary")) {
  617. parse_dictionary(interface);
  618. } else if (lexer.next_is("enum")) {
  619. parse_enumeration(interface);
  620. } else if (lexer.next_is("typedef")) {
  621. parse_typedef(interface);
  622. } else if (lexer.next_is("interface mixin")) {
  623. parse_interface_mixin(interface);
  624. } else if (lexer.next_is("callback")) {
  625. parse_callback_function(extended_attributes, interface);
  626. } else if ((allow_interface && !lexer.next_is("interface")) || !allow_interface) {
  627. auto current_offset = lexer.tell();
  628. auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); });
  629. consume_whitespace();
  630. if (lexer.consume_specific("includes")) {
  631. consume_whitespace();
  632. auto mixin_name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; });
  633. interface.included_mixins.ensure(name).set(mixin_name);
  634. consume_whitespace();
  635. assert_specific(';');
  636. consume_whitespace();
  637. } else {
  638. report_parsing_error("expected 'enum' or 'dictionary'", filename, input, current_offset);
  639. }
  640. } else {
  641. interface.extended_attributes = move(extended_attributes);
  642. break;
  643. }
  644. }
  645. }
  646. void resolve_typedef(Interface& interface, NonnullRefPtr<Type>& type, HashMap<String, String>* extended_attributes = {})
  647. {
  648. if (is<ParameterizedType>(*type)) {
  649. auto parameterized_type = static_ptr_cast<ParameterizedType>(type);
  650. auto& parameters = static_cast<Vector<NonnullRefPtr<Type>>&>(parameterized_type->parameters);
  651. for (auto& parameter : parameters)
  652. resolve_typedef(interface, parameter);
  653. return;
  654. }
  655. auto it = interface.typedefs.find(type->name);
  656. if (it == interface.typedefs.end())
  657. return;
  658. type = it->value.type;
  659. if (!extended_attributes)
  660. return;
  661. for (auto& attribute : it->value.extended_attributes)
  662. extended_attributes->set(attribute.key, attribute.value);
  663. }
  664. void resolve_parameters_typedefs(Interface& interface, Vector<Parameter>& parameters)
  665. {
  666. for (auto& parameter : parameters)
  667. resolve_typedef(interface, parameter.type, &parameter.extended_attributes);
  668. }
  669. template<typename FunctionType>
  670. void resolve_function_typedefs(Interface& interface, FunctionType& function)
  671. {
  672. resolve_typedef(interface, function.return_type);
  673. resolve_parameters_typedefs(interface, function.parameters);
  674. }
  675. NonnullRefPtr<Interface> Parser::parse()
  676. {
  677. auto this_module = Core::File::real_path_for(filename);
  678. auto interface = make_ref_counted<Interface>();
  679. interface->module_own_path = this_module;
  680. s_resolved_imports.set(this_module, interface);
  681. NonnullRefPtrVector<Interface> imports;
  682. while (lexer.consume_specific("#import")) {
  683. consume_whitespace();
  684. assert_specific('<');
  685. auto path = lexer.consume_until('>');
  686. lexer.ignore();
  687. auto maybe_interface = resolve_import(path);
  688. if (maybe_interface.has_value()) {
  689. for (auto& entry : maybe_interface.value()->required_imported_paths)
  690. required_imported_paths.set(entry);
  691. imports.append(maybe_interface.release_value());
  692. }
  693. consume_whitespace();
  694. }
  695. interface->required_imported_paths = required_imported_paths;
  696. parse_non_interface_entities(true, *interface);
  697. if (lexer.consume_specific("interface"))
  698. parse_interface(*interface);
  699. parse_non_interface_entities(false, *interface);
  700. for (auto& import : imports) {
  701. // FIXME: Instead of copying every imported entity into the current interface, query imports directly
  702. for (auto& dictionary : import.dictionaries)
  703. interface->dictionaries.set(dictionary.key, dictionary.value);
  704. for (auto& enumeration : import.enumerations) {
  705. auto enumeration_copy = enumeration.value;
  706. enumeration_copy.is_original_definition = false;
  707. interface->enumerations.set(enumeration.key, move(enumeration_copy));
  708. }
  709. for (auto& typedef_ : import.typedefs)
  710. interface->typedefs.set(typedef_.key, typedef_.value);
  711. for (auto& mixin : import.mixins) {
  712. if (auto it = interface->mixins.find(mixin.key); it != interface->mixins.end() && it->value.ptr() != mixin.value.ptr())
  713. report_parsing_error(String::formatted("Mixin '{}' was already defined in {}", mixin.key, mixin.value->module_own_path), filename, input, lexer.tell());
  714. interface->mixins.set(mixin.key, mixin.value);
  715. }
  716. for (auto& callback_function : import.callback_functions)
  717. interface->callback_functions.set(callback_function.key, callback_function.value);
  718. }
  719. // Resolve mixins
  720. if (auto it = interface->included_mixins.find(interface->name); it != interface->included_mixins.end()) {
  721. for (auto& entry : it->value) {
  722. auto mixin_it = interface->mixins.find(entry);
  723. if (mixin_it == interface->mixins.end())
  724. report_parsing_error(String::formatted("Mixin '{}' was never defined", entry), filename, input, lexer.tell());
  725. auto& mixin = mixin_it->value;
  726. interface->attributes.extend(mixin->attributes);
  727. interface->constants.extend(mixin->constants);
  728. interface->functions.extend(mixin->functions);
  729. interface->static_functions.extend(mixin->static_functions);
  730. if (interface->has_stringifier && mixin->has_stringifier)
  731. report_parsing_error(String::formatted("Both interface '{}' and mixin '{}' have defined stringifier attributes", interface->name, mixin->name), filename, input, lexer.tell());
  732. if (mixin->has_stringifier) {
  733. interface->stringifier_attribute = mixin->stringifier_attribute;
  734. interface->has_stringifier = true;
  735. }
  736. }
  737. }
  738. // Resolve typedefs
  739. for (auto& attribute : interface->attributes)
  740. resolve_typedef(*interface, attribute.type, &attribute.extended_attributes);
  741. for (auto& constant : interface->constants)
  742. resolve_typedef(*interface, constant.type);
  743. for (auto& constructor : interface->constructors)
  744. resolve_parameters_typedefs(*interface, constructor.parameters);
  745. for (auto& function : interface->functions)
  746. resolve_function_typedefs(*interface, function);
  747. for (auto& static_function : interface->static_functions)
  748. resolve_function_typedefs(*interface, static_function);
  749. if (interface->value_iterator_type.has_value())
  750. resolve_typedef(*interface, *interface->value_iterator_type);
  751. if (interface->pair_iterator_types.has_value()) {
  752. resolve_typedef(*interface, interface->pair_iterator_types->get<0>());
  753. resolve_typedef(*interface, interface->pair_iterator_types->get<1>());
  754. }
  755. if (interface->named_property_getter.has_value())
  756. resolve_function_typedefs(*interface, *interface->named_property_getter);
  757. if (interface->named_property_setter.has_value())
  758. resolve_function_typedefs(*interface, *interface->named_property_setter);
  759. if (interface->indexed_property_getter.has_value())
  760. resolve_function_typedefs(*interface, *interface->indexed_property_getter);
  761. if (interface->indexed_property_setter.has_value())
  762. resolve_function_typedefs(*interface, *interface->indexed_property_setter);
  763. if (interface->named_property_deleter.has_value())
  764. resolve_function_typedefs(*interface, *interface->named_property_deleter);
  765. if (interface->named_property_getter.has_value())
  766. resolve_function_typedefs(*interface, *interface->named_property_getter);
  767. for (auto& dictionary : interface->dictionaries) {
  768. for (auto& dictionary_member : dictionary.value.members)
  769. resolve_typedef(*interface, dictionary_member.type, &dictionary_member.extended_attributes);
  770. }
  771. for (auto& callback_function : interface->callback_functions)
  772. resolve_function_typedefs(*interface, callback_function.value);
  773. // Create overload sets
  774. for (auto& function : interface->functions) {
  775. auto& overload_set = interface->overload_sets.ensure(function.name);
  776. function.overload_index = overload_set.size();
  777. overload_set.append(function);
  778. }
  779. for (auto& overload_set : interface->overload_sets) {
  780. if (overload_set.value.size() == 1)
  781. continue;
  782. for (auto& overloaded_function : overload_set.value)
  783. overloaded_function.is_overloaded = true;
  784. }
  785. for (auto& function : interface->static_functions) {
  786. auto& overload_set = interface->static_overload_sets.ensure(function.name);
  787. function.overload_index = overload_set.size();
  788. overload_set.append(function);
  789. }
  790. for (auto& overload_set : interface->static_overload_sets) {
  791. if (overload_set.value.size() == 1)
  792. continue;
  793. for (auto& overloaded_function : overload_set.value)
  794. overloaded_function.is_overloaded = true;
  795. }
  796. // FIXME: Add support for overloading constructors
  797. if (interface->will_generate_code())
  798. interface->required_imported_paths.set(this_module);
  799. interface->imported_modules = move(imports);
  800. return interface;
  801. }
  802. Parser::Parser(String filename, StringView contents, String import_base_path)
  803. : import_base_path(move(import_base_path))
  804. , filename(move(filename))
  805. , input(contents)
  806. , lexer(input)
  807. {
  808. }
  809. }