Parser.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /*
  2. * Copyright (c) 2020-2021, the SerenityOS developers.
  3. * Copyright (c) 2021, Sam Atkins <atkinssj@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/NonnullRefPtrVector.h>
  8. #include <AK/SourceLocation.h>
  9. #include <LibWeb/CSS/CSSStyleDeclaration.h>
  10. #include <LibWeb/CSS/CSSStyleRule.h>
  11. #include <LibWeb/CSS/CSSStyleSheet.h>
  12. #include <LibWeb/CSS/Parser/AtStyleRule.h>
  13. #include <LibWeb/CSS/Parser/DeclarationOrAtRule.h>
  14. #include <LibWeb/CSS/Parser/Parser.h>
  15. #include <LibWeb/CSS/Parser/QualifiedStyleRule.h>
  16. #include <LibWeb/CSS/Parser/StyleBlockRule.h>
  17. #include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
  18. #include <LibWeb/CSS/Parser/StyleFunctionRule.h>
  19. #include <LibWeb/CSS/Selector.h>
  20. #include <LibWeb/DOM/Document.h>
  21. #include <LibWeb/Dump.h>
  22. #define CSS_PARSER_TRACE 1
  23. static void log_parse_error(const SourceLocation& location = SourceLocation::current())
  24. {
  25. dbgln_if(CSS_PARSER_TRACE, "Parse error (CSS) {}", location);
  26. }
  27. namespace Web::CSS {
  28. ParsingContext::ParsingContext()
  29. {
  30. }
  31. ParsingContext::ParsingContext(DOM::Document const& document)
  32. : m_document(&document)
  33. {
  34. }
  35. ParsingContext::ParsingContext(DOM::ParentNode const& parent_node)
  36. : m_document(&parent_node.document())
  37. {
  38. }
  39. bool ParsingContext::in_quirks_mode() const
  40. {
  41. return m_document ? m_document->in_quirks_mode() : false;
  42. }
  43. URL ParsingContext::complete_url(String const& addr) const
  44. {
  45. return m_document ? m_document->url().complete_url(addr) : URL::create_with_url_or_path(addr);
  46. }
  47. Parser::Parser(ParsingContext const& context, StringView const& input, String const& encoding)
  48. : m_context(context)
  49. , m_tokenizer(input, encoding)
  50. {
  51. m_tokens = m_tokenizer.parse();
  52. }
  53. Parser::~Parser()
  54. {
  55. }
  56. Token Parser::peek_token()
  57. {
  58. size_t next_offset = m_iterator_offset + 1;
  59. if (next_offset < m_tokens.size()) {
  60. return m_tokens.at(next_offset);
  61. }
  62. return m_tokens.at(m_iterator_offset);
  63. }
  64. Token Parser::next_token()
  65. {
  66. if (m_iterator_offset < (int)m_tokens.size() - 1) {
  67. ++m_iterator_offset;
  68. }
  69. auto token = m_tokens.at(m_iterator_offset);
  70. return token;
  71. }
  72. Token Parser::current_token()
  73. {
  74. return m_tokens.at(m_iterator_offset);
  75. }
  76. NonnullRefPtr<CSSStyleSheet> Parser::parse_as_stylesheet()
  77. {
  78. auto parser_rules = consume_a_list_of_rules(true);
  79. NonnullRefPtrVector<CSSRule> rules;
  80. for (auto& raw_rule : parser_rules) {
  81. auto rule = convert_rule(raw_rule);
  82. if (rule)
  83. rules.append(*rule);
  84. }
  85. return CSSStyleSheet::create(rules);
  86. }
  87. Vector<Selector> Parser::parse_a_selector()
  88. {
  89. auto comma_separated_lists = parse_as_comma_separated_list_of_component_values();
  90. return parse_a_selector(comma_separated_lists);
  91. }
  92. Vector<Selector> Parser::parse_a_selector(Vector<Vector<StyleComponentValueRule>>& parts)
  93. {
  94. Vector<Selector> selectors;
  95. for (auto& selector_parts : parts) {
  96. auto selector = parse_single_selector(selector_parts);
  97. if (selector.has_value())
  98. selectors.append(selector.value());
  99. }
  100. return selectors;
  101. }
  102. Vector<Selector> Parser::parse_a_relative_selector()
  103. {
  104. auto comma_separated_lists = parse_as_comma_separated_list_of_component_values();
  105. Vector<Selector> selectors;
  106. for (auto& selector_parts : comma_separated_lists) {
  107. auto selector = parse_single_selector(selector_parts, true);
  108. if (selector.has_value())
  109. selectors.append(selector.value());
  110. }
  111. return selectors;
  112. }
  113. Optional<Selector> Parser::parse_single_selector(Vector<StyleComponentValueRule> parts, bool is_relative)
  114. {
  115. // FIXME: Bring this all in line with the spec. https://www.w3.org/TR/selectors-4/
  116. Vector<CSS::Selector::ComplexSelector> selectors;
  117. size_t index = 0;
  118. auto parse_simple_selector = [&]() -> Optional<CSS::Selector::SimpleSelector> {
  119. if (index >= parts.size())
  120. return {};
  121. auto& current_value = parts.at(index);
  122. index++;
  123. CSS::Selector::SimpleSelector::Type type;
  124. String value;
  125. // FIXME: Handle namespace prefixes.
  126. if (current_value.is(Token::TokenType::Delim) && current_value.token().delim() == "*") {
  127. // FIXME: Handle selectors like `*.foo`.
  128. type = CSS::Selector::SimpleSelector::Type::Universal;
  129. CSS::Selector::SimpleSelector result;
  130. result.type = type;
  131. return result;
  132. }
  133. if (current_value.is(Token::TokenType::Hash)) {
  134. if (current_value.token().m_hash_type != Token::HashType::Id) {
  135. dbgln("Selector contains hash token that is not an id: {}", current_value.to_string());
  136. return {};
  137. }
  138. type = CSS::Selector::SimpleSelector::Type::Id;
  139. value = current_value.token().m_value.to_string();
  140. } else if (current_value.is(Token::TokenType::Delim) && current_value.token().delim() == ".") {
  141. if (index >= parts.size())
  142. return {};
  143. current_value = parts.at(index);
  144. index++;
  145. if (!current_value.is(Token::TokenType::Ident)) {
  146. dbgln("Expected an ident after '.', got: {}", current_value.to_string());
  147. return {};
  148. }
  149. type = CSS::Selector::SimpleSelector::Type::Class;
  150. value = current_value.to_string();
  151. } else if (current_value.is(Token::TokenType::Delim) && current_value.token().delim() == "*") {
  152. type = CSS::Selector::SimpleSelector::Type::Universal;
  153. } else {
  154. type = CSS::Selector::SimpleSelector::Type::TagName;
  155. value = current_value.to_string().to_lowercase();
  156. }
  157. CSS::Selector::SimpleSelector simple_selector;
  158. simple_selector.type = type;
  159. simple_selector.value = value;
  160. if (index >= parts.size())
  161. return simple_selector;
  162. current_value = parts.at(index);
  163. index++;
  164. // FIXME: Attribute selectors want to be their own Selector::SimpleSelector::Type according to the spec.
  165. if (current_value.is_block() && current_value.block().is_square()) {
  166. Vector<StyleComponentValueRule> const& attribute_parts = current_value.block().values();
  167. // FIXME: Handle namespace prefix for attribute name.
  168. auto& attribute_part = attribute_parts.first();
  169. if (!attribute_part.is(Token::TokenType::Ident)) {
  170. dbgln("Expected ident for attribute name, got: '{}'", attribute_part.to_string());
  171. return {};
  172. }
  173. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::HasAttribute;
  174. simple_selector.attribute_name = attribute_part.token().ident();
  175. size_t attribute_index = 1;
  176. while (attribute_parts.at(attribute_index).is(Token::TokenType::Whitespace)) {
  177. attribute_index++;
  178. if (attribute_index >= attribute_parts.size())
  179. return simple_selector;
  180. }
  181. auto& delim_part = attribute_parts.at(attribute_index);
  182. if (!delim_part.is(Token::TokenType::Delim)) {
  183. dbgln("Expected a delim for attribute comparison, got: '{}'", delim_part.to_string());
  184. return {};
  185. }
  186. if (delim_part.token().delim() == "=") {
  187. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::ExactValueMatch;
  188. attribute_index++;
  189. } else {
  190. attribute_index++;
  191. auto& delim_second_part = attribute_parts.at(attribute_index);
  192. if (!(delim_part.is(Token::TokenType::Delim) && delim_part.token().delim() == "=")) {
  193. dbgln("Expected a double delim for attribute comparison, got: '{}{}'", delim_part.to_string(), delim_second_part.to_string());
  194. return {};
  195. }
  196. if (delim_part.token().delim() == "~") {
  197. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::ContainsWord;
  198. attribute_index++;
  199. } else if (delim_part.token().delim() == "*") {
  200. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::ContainsString;
  201. attribute_index++;
  202. } else if (delim_part.token().delim() == "|") {
  203. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::StartsWithSegment;
  204. attribute_index++;
  205. } else if (delim_part.token().delim() == "^") {
  206. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::StartsWithString;
  207. attribute_index++;
  208. } else if (delim_part.token().delim() == "$") {
  209. simple_selector.attribute_match_type = CSS::Selector::SimpleSelector::AttributeMatchType::EndsWithString;
  210. attribute_index++;
  211. }
  212. }
  213. while (attribute_parts.at(attribute_index).is(Token::TokenType::Whitespace)) {
  214. attribute_index++;
  215. if (attribute_index >= attribute_parts.size()) {
  216. dbgln("Attribute selector ended without a value to match.");
  217. return {};
  218. }
  219. }
  220. auto& value_part = attribute_parts.at(attribute_index);
  221. if (!value_part.is(Token::TokenType::Ident) && !value_part.is(Token::TokenType::String)) {
  222. dbgln("Expected a string or ident for the value to match attribute against, got: '{}'", value_part.to_string());
  223. return {};
  224. }
  225. simple_selector.attribute_value = value_part.token().is_ident() ? value_part.token().ident() : value_part.token().string();
  226. // FIXME: Handle case-sensitivity suffixes. https://www.w3.org/TR/selectors-4/#attribute-case
  227. return simple_selector;
  228. }
  229. // FIXME: Pseudo-class selectors want to be their own Selector::SimpleSelector::Type according to the spec.
  230. if (current_value.is(Token::TokenType::Colon)) {
  231. bool is_pseudo = false;
  232. current_value = parts.at(index);
  233. index++;
  234. if (index >= parts.size())
  235. return {};
  236. if (current_value.is(Token::TokenType::Colon)) {
  237. is_pseudo = true;
  238. current_value = parts.at(index);
  239. index++;
  240. if (index >= parts.size())
  241. return {};
  242. }
  243. // Ignore for now, otherwise we produce a "false positive" selector
  244. // and apply styles to the element itself, not its pseudo element
  245. if (is_pseudo)
  246. return {};
  247. current_value = parts.at(index);
  248. index++;
  249. if (current_value.is(Token::TokenType::Ident)) {
  250. auto pseudo_name = current_value.token().ident();
  251. if (pseudo_name.equals_ignoring_case("link")) {
  252. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link;
  253. } else if (pseudo_name.equals_ignoring_case("visited")) {
  254. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited;
  255. } else if (pseudo_name.equals_ignoring_case("active")) {
  256. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active;
  257. } else if (pseudo_name.equals_ignoring_case("hover")) {
  258. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover;
  259. } else if (pseudo_name.equals_ignoring_case("focus")) {
  260. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Focus;
  261. } else if (pseudo_name.equals_ignoring_case("first-child")) {
  262. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::FirstChild;
  263. } else if (pseudo_name.equals_ignoring_case("last-child")) {
  264. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::LastChild;
  265. } else if (pseudo_name.equals_ignoring_case("only-child")) {
  266. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::OnlyChild;
  267. } else if (pseudo_name.equals_ignoring_case("empty")) {
  268. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Empty;
  269. } else if (pseudo_name.equals_ignoring_case("root")) {
  270. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Root;
  271. } else if (pseudo_name.equals_ignoring_case("first-of-type")) {
  272. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::FirstOfType;
  273. } else if (pseudo_name.equals_ignoring_case("last-of-type")) {
  274. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::LastOfType;
  275. } else if (pseudo_name.equals_ignoring_case("before")) {
  276. simple_selector.pseudo_element = CSS::Selector::SimpleSelector::PseudoElement::Before;
  277. } else if (pseudo_name.equals_ignoring_case("after")) {
  278. simple_selector.pseudo_element = CSS::Selector::SimpleSelector::PseudoElement::After;
  279. } else if (pseudo_name.equals_ignoring_case("disabled")) {
  280. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Disabled;
  281. } else if (pseudo_name.equals_ignoring_case("enabled")) {
  282. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Enabled;
  283. } else if (pseudo_name.equals_ignoring_case("checked")) {
  284. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Checked;
  285. } else {
  286. dbgln("Unknown pseudo class: '{}'", pseudo_name);
  287. return simple_selector;
  288. }
  289. } else if (current_value.is_function()) {
  290. auto& pseudo_function = current_value.function();
  291. if (pseudo_function.name().equals_ignoring_case("nth-child")) {
  292. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::NthChild;
  293. simple_selector.nth_child_pattern = CSS::Selector::SimpleSelector::NthChildPattern::parse(pseudo_function.values_as_string());
  294. } else if (pseudo_function.name().equals_ignoring_case("nth-last-child")) {
  295. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::NthLastChild;
  296. simple_selector.nth_child_pattern = CSS::Selector::SimpleSelector::NthChildPattern::parse(pseudo_function.values_as_string());
  297. } else if (pseudo_function.name().equals_ignoring_case("not")) {
  298. simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Not;
  299. simple_selector.not_selector = pseudo_function.values_as_string();
  300. } else {
  301. dbgln("Unknown pseudo class: '{}'()", pseudo_function.name());
  302. return simple_selector;
  303. }
  304. } else {
  305. dbgln("Unexpected Block in pseudo-class name, expected a function or identifier. '{}'", current_value.to_string());
  306. return simple_selector;
  307. }
  308. }
  309. return simple_selector;
  310. };
  311. auto parse_complex_selector = [&]() -> Optional<CSS::Selector::ComplexSelector> {
  312. auto relation = CSS::Selector::ComplexSelector::Relation::Descendant;
  313. if (index >= parts.size())
  314. return {};
  315. auto current_value = parts.at(index);
  316. if (current_value.is(Token::TokenType::Delim)) {
  317. auto delim = current_value.token().delim();
  318. if (delim == ">") {
  319. relation = CSS::Selector::ComplexSelector::Relation::ImmediateChild;
  320. index++;
  321. } else if (delim == "+") {
  322. relation = CSS::Selector::ComplexSelector::Relation::AdjacentSibling;
  323. index++;
  324. } else if (delim == "~") {
  325. relation = CSS::Selector::ComplexSelector::Relation::GeneralSibling;
  326. index++;
  327. } else if (delim == "|") {
  328. if (index + 1 >= parts.size())
  329. return {};
  330. auto next = parts.at(index + 1);
  331. if (next.is(Token::TokenType::Delim) && next.token().delim() == "|") {
  332. relation = CSS::Selector::ComplexSelector::Relation::Column;
  333. index += 2;
  334. }
  335. }
  336. }
  337. Vector<CSS::Selector::SimpleSelector> simple_selectors;
  338. for (;;) {
  339. auto component = parse_simple_selector();
  340. if (!component.has_value())
  341. break;
  342. simple_selectors.append(component.value());
  343. }
  344. if (simple_selectors.is_empty())
  345. return {};
  346. return CSS::Selector::ComplexSelector { relation, move(simple_selectors) };
  347. };
  348. for (;;) {
  349. auto complex = parse_complex_selector();
  350. if (complex.has_value())
  351. selectors.append(complex.value());
  352. if (index >= parts.size())
  353. break;
  354. auto current_value = parts.at(index);
  355. if (current_value.is(Token::TokenType::Comma))
  356. break;
  357. index++;
  358. }
  359. if (selectors.is_empty())
  360. return {};
  361. if (!is_relative)
  362. selectors.first().relation = CSS::Selector::ComplexSelector::Relation::None;
  363. return Selector(move(selectors));
  364. }
  365. void Parser::dump_all_tokens()
  366. {
  367. dbgln("Dumping all tokens:");
  368. for (auto& token : m_tokens)
  369. dbgln("{}", token.to_string());
  370. }
  371. void Parser::reconsume_current_input_token()
  372. {
  373. --m_iterator_offset;
  374. }
  375. NonnullRefPtrVector<QualifiedStyleRule> Parser::consume_a_list_of_rules(bool top_level)
  376. {
  377. NonnullRefPtrVector<QualifiedStyleRule> rules;
  378. for (;;) {
  379. auto token = next_token();
  380. if (token.is_whitespace()) {
  381. continue;
  382. }
  383. if (token.is_eof()) {
  384. break;
  385. }
  386. if (token.is_cdo() || token.is_cdc()) {
  387. if (top_level) {
  388. continue;
  389. }
  390. reconsume_current_input_token();
  391. auto maybe_qualified = consume_a_qualified_rule();
  392. if (maybe_qualified) {
  393. rules.append(maybe_qualified.release_nonnull());
  394. }
  395. continue;
  396. }
  397. if (token.is_at()) {
  398. reconsume_current_input_token();
  399. rules.append(consume_an_at_rule());
  400. continue;
  401. }
  402. reconsume_current_input_token();
  403. auto maybe_qualified = consume_a_qualified_rule();
  404. if (maybe_qualified) {
  405. rules.append(maybe_qualified.release_nonnull());
  406. }
  407. }
  408. return rules;
  409. }
  410. NonnullRefPtr<AtStyleRule> Parser::consume_an_at_rule()
  411. {
  412. auto initial = next_token();
  413. AtStyleRule rule;
  414. rule.m_name = initial.m_value.to_string();
  415. for (;;) {
  416. auto token = next_token();
  417. if (token.is_semicolon()) {
  418. return rule;
  419. }
  420. if (token.is_eof()) {
  421. log_parse_error();
  422. return rule;
  423. }
  424. if (token.is_open_curly()) {
  425. rule.m_block = consume_a_simple_block();
  426. return rule;
  427. }
  428. // how is "simple block with an associated token of <{-token>" a valid token?
  429. reconsume_current_input_token();
  430. auto value = consume_a_component_value();
  431. rule.m_prelude.append(value);
  432. }
  433. }
  434. RefPtr<QualifiedStyleRule> Parser::consume_a_qualified_rule()
  435. {
  436. NonnullRefPtr<QualifiedStyleRule> rule = create<QualifiedStyleRule>();
  437. for (;;) {
  438. auto token = next_token();
  439. if (token.is_eof()) {
  440. log_parse_error();
  441. return {};
  442. }
  443. if (token.is_open_curly()) {
  444. rule->m_block = consume_a_simple_block();
  445. return rule;
  446. }
  447. // how is "simple block with an associated token of <{-token>" a valid token?
  448. reconsume_current_input_token();
  449. auto value = consume_a_component_value();
  450. rule->m_prelude.append(value);
  451. }
  452. return rule;
  453. }
  454. StyleComponentValueRule Parser::consume_a_component_value()
  455. {
  456. auto token = next_token();
  457. if (token.is_open_curly() || token.is_open_square() || token.is_open_paren()) {
  458. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Block);
  459. component.m_block = consume_a_simple_block();
  460. return component;
  461. }
  462. if (token.is_function()) {
  463. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Function);
  464. component.m_function = consume_a_function();
  465. return component;
  466. }
  467. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Token);
  468. component.m_token = token;
  469. return component;
  470. }
  471. NonnullRefPtr<StyleBlockRule> Parser::consume_a_simple_block()
  472. {
  473. auto ending_token = current_token().mirror_variant();
  474. NonnullRefPtr<StyleBlockRule> block = create<StyleBlockRule>();
  475. block->m_token = current_token();
  476. for (;;) {
  477. auto token = next_token();
  478. if (token.m_type == ending_token) {
  479. return block;
  480. }
  481. if (token.is_eof()) {
  482. log_parse_error();
  483. return block;
  484. }
  485. reconsume_current_input_token();
  486. auto value = consume_a_component_value();
  487. if (value.m_type == StyleComponentValueRule::ComponentType::Token) {
  488. if (value.m_token.is_whitespace()) {
  489. continue;
  490. }
  491. }
  492. block->m_values.append(value);
  493. }
  494. }
  495. NonnullRefPtr<StyleFunctionRule> Parser::consume_a_function()
  496. {
  497. NonnullRefPtr<StyleFunctionRule> function = create<StyleFunctionRule>(current_token().m_value.to_string());
  498. for (;;) {
  499. auto token = next_token();
  500. if (token.is_close_paren()) {
  501. return function;
  502. }
  503. if (token.is_eof()) {
  504. log_parse_error();
  505. return function;
  506. }
  507. reconsume_current_input_token();
  508. auto value = consume_a_component_value();
  509. if (value.m_type == StyleComponentValueRule::ComponentType::Token) {
  510. if (value.m_token.is_whitespace()) {
  511. continue;
  512. }
  513. }
  514. function->m_values.append(value.to_string());
  515. }
  516. return function;
  517. }
  518. Optional<StyleDeclarationRule> Parser::consume_a_declaration(Vector<StyleComponentValueRule>)
  519. {
  520. TODO();
  521. }
  522. Optional<StyleDeclarationRule> Parser::consume_a_declaration()
  523. {
  524. auto token = next_token();
  525. StyleDeclarationRule declaration;
  526. declaration.m_name = token.m_value.to_string();
  527. for (;;) {
  528. if (!peek_token().is_whitespace()) {
  529. break;
  530. }
  531. next_token();
  532. }
  533. auto colon = next_token();
  534. if (!colon.is_colon()) {
  535. log_parse_error();
  536. return {};
  537. }
  538. for (;;) {
  539. if (!peek_token().is_whitespace()) {
  540. break;
  541. }
  542. next_token();
  543. }
  544. for (;;) {
  545. if (peek_token().is_eof()) {
  546. break;
  547. }
  548. declaration.m_values.append(consume_a_component_value());
  549. }
  550. auto second_last = declaration.m_values.at(declaration.m_values.size() - 2);
  551. auto last = declaration.m_values.at(declaration.m_values.size() - 1);
  552. if (second_last.m_type == StyleComponentValueRule::ComponentType::Token && last.m_type == StyleComponentValueRule::ComponentType::Token) {
  553. auto last_token = last.m_token;
  554. auto second_last_token = second_last.m_token;
  555. if (second_last_token.is_delim() && second_last_token.m_value.to_string().equals_ignoring_case("!")) {
  556. if (last_token.is_ident() && last_token.m_value.to_string().equals_ignoring_case("important")) {
  557. declaration.m_values.remove(declaration.m_values.size() - 2);
  558. declaration.m_values.remove(declaration.m_values.size() - 1);
  559. declaration.m_important = true;
  560. }
  561. }
  562. }
  563. for (;;) {
  564. auto maybe_whitespace = declaration.m_values.at(declaration.m_values.size() - 1);
  565. if (!(maybe_whitespace.m_type == StyleComponentValueRule::ComponentType::Token && maybe_whitespace.m_token.is_whitespace())) {
  566. break;
  567. }
  568. declaration.m_values.remove(declaration.m_values.size() - 1);
  569. }
  570. return declaration;
  571. }
  572. Vector<DeclarationOrAtRule> Parser::consume_a_list_of_declarations()
  573. {
  574. Vector<DeclarationOrAtRule> list;
  575. for (;;) {
  576. auto token = next_token();
  577. if (token.is_whitespace() || token.is_semicolon()) {
  578. continue;
  579. }
  580. if (token.is_eof()) {
  581. return list;
  582. }
  583. if (token.is_at()) {
  584. reconsume_current_input_token();
  585. list.append(DeclarationOrAtRule(consume_an_at_rule()));
  586. continue;
  587. }
  588. if (token.is_ident()) {
  589. Vector<StyleComponentValueRule> temp;
  590. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Token);
  591. component.m_token = token;
  592. temp.append(component);
  593. for (;;) {
  594. auto peek = peek_token();
  595. if (peek.is_semicolon() || peek.is_eof()) {
  596. break;
  597. }
  598. temp.append(consume_a_component_value());
  599. }
  600. auto maybe_declaration = consume_a_declaration(temp);
  601. if (maybe_declaration.has_value()) {
  602. list.append(DeclarationOrAtRule(maybe_declaration.value()));
  603. }
  604. }
  605. log_parse_error();
  606. reconsume_current_input_token();
  607. auto peek = peek_token();
  608. if (!(peek.is_semicolon() || peek.is_eof())) {
  609. consume_a_component_value();
  610. }
  611. }
  612. return list;
  613. }
  614. RefPtr<CSSRule> Parser::parse_as_rule()
  615. {
  616. RefPtr<CSSRule> rule;
  617. for (;;) {
  618. auto maybe_whitespace = peek_token();
  619. if (!maybe_whitespace.is_whitespace()) {
  620. break;
  621. }
  622. next_token();
  623. }
  624. auto token = peek_token();
  625. if (token.is_eof()) {
  626. return {};
  627. } else if (token.is_at()) {
  628. auto at_rule = consume_an_at_rule();
  629. rule = convert_rule(at_rule);
  630. } else {
  631. auto qualified_rule = consume_a_qualified_rule();
  632. if (!qualified_rule)
  633. return {};
  634. rule = convert_rule(*qualified_rule);
  635. }
  636. for (;;) {
  637. auto maybe_whitespace = peek_token();
  638. if (!maybe_whitespace.is_whitespace()) {
  639. break;
  640. }
  641. next_token();
  642. }
  643. auto maybe_eof = peek_token();
  644. if (maybe_eof.is_eof()) {
  645. return rule;
  646. }
  647. return {};
  648. }
  649. NonnullRefPtrVector<CSSRule> Parser::parse_as_list_of_rules()
  650. {
  651. auto parsed_rules = consume_a_list_of_rules(false);
  652. NonnullRefPtrVector<CSSRule> rules;
  653. for (auto& rule : parsed_rules) {
  654. auto converted_rule = convert_rule(rule);
  655. if (converted_rule)
  656. rules.append(*converted_rule);
  657. }
  658. return rules;
  659. }
  660. Optional<StyleProperty> Parser::parse_as_declaration()
  661. {
  662. for (;;) {
  663. auto maybe_whitespace = peek_token();
  664. if (!maybe_whitespace.is_whitespace()) {
  665. break;
  666. }
  667. next_token();
  668. }
  669. auto token = peek_token();
  670. if (!token.is_ident()) {
  671. return {};
  672. }
  673. auto declaration = consume_a_declaration();
  674. // FIXME: Return the declaration.
  675. return {};
  676. }
  677. Vector<StyleProperty> Parser::parse_as_list_of_declarations()
  678. {
  679. auto declarations = consume_a_list_of_declarations();
  680. // FIXME: Return the declarations.
  681. return {};
  682. }
  683. Optional<StyleComponentValueRule> Parser::parse_as_component_value()
  684. {
  685. for (;;) {
  686. auto maybe_whitespace = peek_token();
  687. if (!maybe_whitespace.is_whitespace()) {
  688. break;
  689. }
  690. next_token();
  691. }
  692. auto token = peek_token();
  693. if (token.is_eof()) {
  694. return {};
  695. }
  696. auto value = consume_a_component_value();
  697. for (;;) {
  698. auto maybe_whitespace = peek_token();
  699. if (!maybe_whitespace.is_whitespace()) {
  700. break;
  701. }
  702. next_token();
  703. }
  704. auto maybe_eof = peek_token();
  705. if (maybe_eof.is_eof()) {
  706. return value;
  707. }
  708. return {};
  709. }
  710. Vector<StyleComponentValueRule> Parser::parse_as_list_of_component_values()
  711. {
  712. Vector<StyleComponentValueRule> rules;
  713. for (;;) {
  714. if (peek_token().is_eof()) {
  715. break;
  716. }
  717. rules.append(consume_a_component_value());
  718. }
  719. return rules;
  720. }
  721. Vector<Vector<StyleComponentValueRule>> Parser::parse_as_comma_separated_list_of_component_values()
  722. {
  723. Vector<Vector<StyleComponentValueRule>> lists;
  724. lists.append({});
  725. for (;;) {
  726. auto next = next_token();
  727. if (next.is_comma()) {
  728. lists.append({});
  729. continue;
  730. } else if (next.is_eof()) {
  731. break;
  732. }
  733. reconsume_current_input_token();
  734. auto component_value = consume_a_component_value();
  735. lists.last().append(component_value);
  736. }
  737. for (auto& list : lists) {
  738. if (!list.is_empty() && list.first().is(Token::TokenType::Whitespace))
  739. list.take_first();
  740. if (!list.is_empty() && list.last().is(Token::TokenType::Whitespace))
  741. list.take_last();
  742. }
  743. return lists;
  744. }
  745. RefPtr<CSSRule> Parser::convert_rule(NonnullRefPtr<QualifiedStyleRule>)
  746. {
  747. return {};
  748. }
  749. }