Parser.cpp 24 KB

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