Parser.cpp 27 KB

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