Parser.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  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() - 1) {
  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. if (index >= parts.size())
  270. return {};
  271. auto current_value = parts.at(index);
  272. if (current_value.is(Token::TokenType::Delim)) {
  273. auto delim = current_value.token().delim();
  274. if (delim == ">") {
  275. relation = CSS::Selector::ComplexSelector::Relation::ImmediateChild;
  276. index++;
  277. } else if (delim == "+") {
  278. relation = CSS::Selector::ComplexSelector::Relation::AdjacentSibling;
  279. index++;
  280. } else if (delim == "~") {
  281. relation = CSS::Selector::ComplexSelector::Relation::GeneralSibling;
  282. index++;
  283. } else if (delim == "|") {
  284. if (index + 1 >= parts.size())
  285. return {};
  286. auto next = parts.at(index + 1);
  287. if (next.is(Token::TokenType::Delim) && next.token().delim() == "|") {
  288. relation = CSS::Selector::ComplexSelector::Relation::Column;
  289. index += 2;
  290. }
  291. }
  292. }
  293. Vector<CSS::Selector::SimpleSelector> simple_selectors;
  294. for (;;) {
  295. auto component = parse_simple_selector();
  296. if (!component.has_value())
  297. break;
  298. simple_selectors.append(component.value());
  299. }
  300. if (simple_selectors.is_empty())
  301. return {};
  302. return CSS::Selector::ComplexSelector { relation, move(simple_selectors) };
  303. };
  304. for (;;) {
  305. auto complex = parse_complex_selector();
  306. if (complex.has_value())
  307. selectors.append(complex.value());
  308. if (index >= parts.size())
  309. break;
  310. auto current_value = parts.at(index);
  311. if (current_value.is(Token::TokenType::Comma))
  312. break;
  313. index++;
  314. }
  315. if (selectors.is_empty())
  316. return {};
  317. selectors.first().relation = CSS::Selector::ComplexSelector::Relation::None;
  318. return selectors;
  319. }
  320. void Parser::dump_all_tokens()
  321. {
  322. dbgln("Dumping all tokens:");
  323. for (auto& token : m_tokens)
  324. dbgln("{}", token.to_string());
  325. }
  326. void Parser::reconsume_current_input_token()
  327. {
  328. --m_iterator_offset;
  329. }
  330. NonnullRefPtrVector<QualifiedStyleRule> Parser::consume_a_list_of_rules(bool top_level)
  331. {
  332. NonnullRefPtrVector<QualifiedStyleRule> rules;
  333. for (;;) {
  334. auto token = next_token();
  335. if (token.is_whitespace()) {
  336. continue;
  337. }
  338. if (token.is_eof()) {
  339. break;
  340. }
  341. if (token.is_cdo() || token.is_cdc()) {
  342. if (top_level) {
  343. continue;
  344. }
  345. reconsume_current_input_token();
  346. auto maybe_qualified = consume_a_qualified_rule();
  347. if (maybe_qualified) {
  348. rules.append(maybe_qualified.release_nonnull());
  349. }
  350. continue;
  351. }
  352. if (token.is_at()) {
  353. reconsume_current_input_token();
  354. rules.append(consume_an_at_rule());
  355. continue;
  356. }
  357. reconsume_current_input_token();
  358. auto maybe_qualified = consume_a_qualified_rule();
  359. if (maybe_qualified) {
  360. rules.append(maybe_qualified.release_nonnull());
  361. }
  362. }
  363. return rules;
  364. }
  365. NonnullRefPtr<AtStyleRule> Parser::consume_an_at_rule()
  366. {
  367. auto initial = next_token();
  368. AtStyleRule rule;
  369. rule.m_name = initial.m_value.to_string();
  370. for (;;) {
  371. auto token = next_token();
  372. if (token.is_semicolon()) {
  373. return rule;
  374. }
  375. if (token.is_eof()) {
  376. log_parse_error();
  377. return rule;
  378. }
  379. if (token.is_open_curly()) {
  380. rule.m_block = consume_a_simple_block();
  381. return rule;
  382. }
  383. // how is "simple block with an associated token of <{-token>" a valid token?
  384. reconsume_current_input_token();
  385. auto value = consume_a_component_value();
  386. rule.m_prelude.append(value);
  387. }
  388. }
  389. RefPtr<QualifiedStyleRule> Parser::consume_a_qualified_rule()
  390. {
  391. NonnullRefPtr<QualifiedStyleRule> rule = create<QualifiedStyleRule>();
  392. for (;;) {
  393. auto token = next_token();
  394. if (token.is_eof()) {
  395. log_parse_error();
  396. return {};
  397. }
  398. if (token.is_open_curly()) {
  399. rule->m_block = consume_a_simple_block();
  400. return rule;
  401. }
  402. // how is "simple block with an associated token of <{-token>" a valid token?
  403. reconsume_current_input_token();
  404. auto value = consume_a_component_value();
  405. rule->m_prelude.append(value);
  406. }
  407. return rule;
  408. }
  409. StyleComponentValueRule Parser::consume_a_component_value()
  410. {
  411. auto token = next_token();
  412. if (token.is_open_curly() || token.is_open_square() || token.is_open_paren()) {
  413. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Block);
  414. component.m_block = consume_a_simple_block();
  415. return component;
  416. }
  417. if (token.is_function()) {
  418. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Function);
  419. component.m_function = consume_a_function();
  420. return component;
  421. }
  422. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Token);
  423. component.m_token = token;
  424. return component;
  425. }
  426. NonnullRefPtr<StyleBlockRule> Parser::consume_a_simple_block()
  427. {
  428. auto ending_token = current_token().mirror_variant();
  429. NonnullRefPtr<StyleBlockRule> block = create<StyleBlockRule>();
  430. block->m_token = current_token();
  431. for (;;) {
  432. auto token = next_token();
  433. if (token.m_type == ending_token) {
  434. return block;
  435. }
  436. if (token.is_eof()) {
  437. log_parse_error();
  438. return block;
  439. }
  440. reconsume_current_input_token();
  441. auto value = consume_a_component_value();
  442. if (value.m_type == StyleComponentValueRule::ComponentType::Token) {
  443. if (value.m_token.is_whitespace()) {
  444. continue;
  445. }
  446. }
  447. block->m_values.append(value);
  448. }
  449. }
  450. NonnullRefPtr<StyleFunctionRule> Parser::consume_a_function()
  451. {
  452. NonnullRefPtr<StyleFunctionRule> function = create<StyleFunctionRule>(current_token().m_value.to_string());
  453. for (;;) {
  454. auto token = next_token();
  455. if (token.is_close_paren()) {
  456. return function;
  457. }
  458. if (token.is_eof()) {
  459. log_parse_error();
  460. return function;
  461. }
  462. reconsume_current_input_token();
  463. auto value = consume_a_component_value();
  464. if (value.m_type == StyleComponentValueRule::ComponentType::Token) {
  465. if (value.m_token.is_whitespace()) {
  466. continue;
  467. }
  468. }
  469. function->m_values.append(value.to_string());
  470. }
  471. return function;
  472. }
  473. Optional<StyleDeclarationRule> Parser::consume_a_declaration(Vector<StyleComponentValueRule>)
  474. {
  475. TODO();
  476. }
  477. Optional<StyleDeclarationRule> Parser::consume_a_declaration()
  478. {
  479. auto token = next_token();
  480. StyleDeclarationRule declaration;
  481. declaration.m_name = token.m_value.to_string();
  482. for (;;) {
  483. if (!peek_token().is_whitespace()) {
  484. break;
  485. }
  486. next_token();
  487. }
  488. auto colon = next_token();
  489. if (!colon.is_colon()) {
  490. log_parse_error();
  491. return {};
  492. }
  493. for (;;) {
  494. if (!peek_token().is_whitespace()) {
  495. break;
  496. }
  497. next_token();
  498. }
  499. for (;;) {
  500. if (peek_token().is_eof()) {
  501. break;
  502. }
  503. declaration.m_values.append(consume_a_component_value());
  504. }
  505. auto second_last = declaration.m_values.at(declaration.m_values.size() - 2);
  506. auto last = declaration.m_values.at(declaration.m_values.size() - 1);
  507. if (second_last.m_type == StyleComponentValueRule::ComponentType::Token && last.m_type == StyleComponentValueRule::ComponentType::Token) {
  508. auto last_token = last.m_token;
  509. auto second_last_token = second_last.m_token;
  510. if (second_last_token.is_delim() && second_last_token.m_value.to_string().equals_ignoring_case("!")) {
  511. if (last_token.is_ident() && last_token.m_value.to_string().equals_ignoring_case("important")) {
  512. declaration.m_values.remove(declaration.m_values.size() - 2);
  513. declaration.m_values.remove(declaration.m_values.size() - 1);
  514. declaration.m_important = true;
  515. }
  516. }
  517. }
  518. for (;;) {
  519. auto maybe_whitespace = declaration.m_values.at(declaration.m_values.size() - 1);
  520. if (!(maybe_whitespace.m_type == StyleComponentValueRule::ComponentType::Token && maybe_whitespace.m_token.is_whitespace())) {
  521. break;
  522. }
  523. declaration.m_values.remove(declaration.m_values.size() - 1);
  524. }
  525. return declaration;
  526. }
  527. Vector<DeclarationOrAtRule> Parser::consume_a_list_of_declarations()
  528. {
  529. Vector<DeclarationOrAtRule> list;
  530. for (;;) {
  531. auto token = next_token();
  532. if (token.is_whitespace() || token.is_semicolon()) {
  533. continue;
  534. }
  535. if (token.is_eof()) {
  536. return list;
  537. }
  538. if (token.is_at()) {
  539. reconsume_current_input_token();
  540. list.append(DeclarationOrAtRule(consume_an_at_rule()));
  541. continue;
  542. }
  543. if (token.is_ident()) {
  544. Vector<StyleComponentValueRule> temp;
  545. auto component = StyleComponentValueRule(StyleComponentValueRule::ComponentType::Token);
  546. component.m_token = token;
  547. temp.append(component);
  548. for (;;) {
  549. auto peek = peek_token();
  550. if (peek.is_semicolon() || peek.is_eof()) {
  551. break;
  552. }
  553. temp.append(consume_a_component_value());
  554. }
  555. auto maybe_declaration = consume_a_declaration(temp);
  556. if (maybe_declaration.has_value()) {
  557. list.append(DeclarationOrAtRule(maybe_declaration.value()));
  558. }
  559. }
  560. log_parse_error();
  561. reconsume_current_input_token();
  562. auto peek = peek_token();
  563. if (!(peek.is_semicolon() || peek.is_eof())) {
  564. consume_a_component_value();
  565. }
  566. }
  567. return list;
  568. }
  569. RefPtr<QualifiedStyleRule> Parser::parse_as_rule()
  570. {
  571. RefPtr<QualifiedStyleRule> rule;
  572. for (;;) {
  573. auto maybe_whitespace = peek_token();
  574. if (!maybe_whitespace.is_whitespace()) {
  575. break;
  576. }
  577. next_token();
  578. }
  579. auto token = peek_token();
  580. if (token.is_eof()) {
  581. return {};
  582. }
  583. if (token.is_at()) {
  584. rule = consume_an_at_rule();
  585. } else {
  586. rule = consume_a_qualified_rule();
  587. }
  588. for (;;) {
  589. auto maybe_whitespace = peek_token();
  590. if (!maybe_whitespace.is_whitespace()) {
  591. break;
  592. }
  593. next_token();
  594. }
  595. auto maybe_eof = peek_token();
  596. if (maybe_eof.is_eof()) {
  597. return rule;
  598. }
  599. return {};
  600. }
  601. NonnullRefPtrVector<QualifiedStyleRule> Parser::parse_as_list_of_rules()
  602. {
  603. return consume_a_list_of_rules(false);
  604. }
  605. Optional<StyleDeclarationRule> Parser::parse_as_declaration()
  606. {
  607. for (;;) {
  608. auto maybe_whitespace = peek_token();
  609. if (!maybe_whitespace.is_whitespace()) {
  610. break;
  611. }
  612. next_token();
  613. }
  614. auto token = peek_token();
  615. if (!token.is_ident()) {
  616. return {};
  617. }
  618. return consume_a_declaration();
  619. }
  620. Vector<DeclarationOrAtRule> Parser::parse_as_list_of_declarations()
  621. {
  622. return consume_a_list_of_declarations();
  623. }
  624. Optional<StyleComponentValueRule> Parser::parse_as_component_value()
  625. {
  626. for (;;) {
  627. auto maybe_whitespace = peek_token();
  628. if (!maybe_whitespace.is_whitespace()) {
  629. break;
  630. }
  631. next_token();
  632. }
  633. auto token = peek_token();
  634. if (token.is_eof()) {
  635. return {};
  636. }
  637. auto value = consume_a_component_value();
  638. for (;;) {
  639. auto maybe_whitespace = peek_token();
  640. if (!maybe_whitespace.is_whitespace()) {
  641. break;
  642. }
  643. next_token();
  644. }
  645. auto maybe_eof = peek_token();
  646. if (maybe_eof.is_eof()) {
  647. return value;
  648. }
  649. return {};
  650. }
  651. Vector<StyleComponentValueRule> Parser::parse_as_list_of_component_values()
  652. {
  653. Vector<StyleComponentValueRule> rules;
  654. for (;;) {
  655. if (peek_token().is_eof()) {
  656. break;
  657. }
  658. rules.append(consume_a_component_value());
  659. }
  660. return rules;
  661. }
  662. Vector<StyleComponentValueRule> Parser::parse_as_list_of_comma_separated_component_values()
  663. {
  664. Vector<StyleComponentValueRule> rules;
  665. for (;;) {
  666. rules.append(consume_a_component_value());
  667. if (peek_token().is_comma())
  668. continue;
  669. if (peek_token().is_eof())
  670. break;
  671. }
  672. return rules;
  673. }
  674. }