8 #ifndef INCLUDED_ORCUS_CSS_PARSER_HPP
9 #define INCLUDED_ORCUS_CSS_PARSER_HPP
11 #define ORCUS_DEBUG_CSS 0
13 #include "parser_global.hpp"
14 #include "css_parser_base.hpp"
35 void at_rule_name(
const char* p,
size_t n)
40 void simple_selector_type(
const char* p,
size_t n)
45 void simple_selector_class(
const char* p,
size_t n)
50 void simple_selector_pseudo_element(orcus::css::pseudo_element_t pe)
55 void simple_selector_pseudo_class(orcus::css::pseudo_class_t pc)
60 void simple_selector_id(
const char* p,
size_t n)
65 void end_simple_selector() {}
67 void end_selector() {}
69 void combinator(orcus::css::combinator_t combinator)
91 void value(
const char* p,
size_t n)
103 void rgb(uint8_t red, uint8_t green, uint8_t blue)
105 (void)red; (void)green; (void)blue;
117 void rgba(uint8_t red, uint8_t green, uint8_t blue,
double alpha)
119 (void)red; (void)green; (void)blue; (void)alpha;
129 void hsl(uint8_t hue, uint8_t sat, uint8_t light)
131 (void)hue; (void)sat; (void)light;
143 void hsla(uint8_t hue, uint8_t sat, uint8_t light,
double alpha)
145 (void)hue; (void)sat; (void)light; (void)alpha;
154 void url(
const char* p,
size_t n)
192 template<
typename _Handler>
196 typedef _Handler handler_type;
198 css_parser(
const char* p,
size_t n, handler_type& hdl);
208 void simple_selector_name();
209 void property_name();
211 void quoted_value(
char c);
213 void function_value(std::string_view v);
214 void function_rgb(
bool alpha);
215 void function_hsl(
bool alpha);
221 handler_type& m_handler;
224 template<
typename _Handler>
228 template<
typename _Handler>
229 void css_parser<_Handler>::parse()
234 std::cout <<
"compressed: '";
235 const char* p = mp_char;
236 for (; p != mp_end; ++p)
238 std::cout <<
"'" << std::endl;
240 m_handler.begin_parse();
243 m_handler.end_parse();
246 template<
typename _Handler>
247 void css_parser<_Handler>::rule()
258 simple_selector_name();
265 set_combinator(c, css::combinator_t::direct_child);
268 set_combinator(c, css::combinator_t::next_sibling);
273 simple_selector_name();
279 reset_before_block();
283 css::parse_error::throw_with(
"rule: failed to parse '", c,
"'");
288 template<
typename _Handler>
289 void css_parser<_Handler>::at_rule_name()
292 assert(cur_char() ==
'@');
296 throw css::parse_error(
"at_rule_name: first character of an at-rule name must be an alphabet.");
303 m_handler.at_rule_name(p, len);
305 std::string foo(p, len);
306 std::cout <<
"at-rule name: " << foo.c_str() << std::endl;
310 template<
typename _Handler>
311 void css_parser<_Handler>::simple_selector_name()
322 if (m_simple_selector_count)
325 cout <<
"combinator: " << m_combinator << endl;
327 m_handler.combinator(m_combinator);
328 m_combinator = css::combinator_t::descendant;
330 assert(is_alpha(c) || c ==
'.' || c ==
'#');
332 const char* p =
nullptr;
336 cout <<
"simple_selector_name: (" << m_simple_selector_count <<
")";
339 if (c !=
'.' && c !=
'#')
344 cout <<
" type=" << s;
346 m_handler.simple_selector_type(p, n);
350 while (in_loop && has_char())
358 m_handler.simple_selector_class(p, n);
361 std::cout <<
" class=" << s;
369 m_handler.simple_selector_id(p, n);
372 std::cout <<
" id=" << s;
380 if (cur_char() ==
':')
385 css::pseudo_element_t elem = css::to_pseudo_element({p, n});
387 css::parse_error::throw_with(
388 "selector_name: unknown pseudo element '", p, n,
"'");
390 m_handler.simple_selector_pseudo_element(elem);
396 css::pseudo_class_t pc = css::to_pseudo_class({p, n});
398 css::parse_error::throw_with(
399 "selector_name: unknown pseudo class '", p, n,
"'");
401 m_handler.simple_selector_pseudo_class(pc);
410 m_handler.end_simple_selector();
411 skip_comments_and_blanks();
413 ++m_simple_selector_count;
416 std::cout << std::endl;
420 template<
typename _Handler>
421 void css_parser<_Handler>::property_name()
427 if (!is_alpha(c) && c !=
'.')
428 css::parse_error::throw_with(
429 "property_name: first character of a name must be an alphabet or a dot, but found '", c,
"'");
434 skip_comments_and_blanks();
436 m_handler.property_name(p, len);
438 std::string foo(p, len);
439 std::cout <<
"property name: " << foo.c_str() << std::endl;
443 template<
typename _Handler>
444 void css_parser<_Handler>::property()
448 m_handler.begin_property();
450 if (cur_char() !=
':')
451 throw css::parse_error(
"property: ':' expected.");
453 skip_comments_and_blanks();
456 while (in_loop && has_char())
466 skip_comments_and_blanks();
478 skip_comments_and_blanks();
479 m_handler.end_property();
482 template<
typename _Handler>
483 void css_parser<_Handler>::quoted_value(
char c)
486 const char* p =
nullptr;
492 m_handler.value(p, len);
494 std::string foo(p, len);
495 std::cout <<
"quoted value: " << foo.c_str() << std::endl;
499 template<
typename _Handler>
500 void css_parser<_Handler>::value()
504 if (c ==
'"' || c ==
'\'')
510 std::string_view v = parse_value();
514 if (cur_char() ==
'(')
520 m_handler.value(v.data(), v.size());
522 skip_comments_and_blanks();
525 std::cout <<
"value: " << v << std::endl;
529 template<
typename _Handler>
530 void css_parser<_Handler>::function_value(std::string_view v)
532 assert(cur_char() ==
'(');
533 css::property_function_t func = css::to_property_function(v);
534 if (func == css::property_function_t::unknown)
535 css::parse_error::throw_with(
"function_value: unknown function '", v,
"'");
539 skip_comments_and_blanks();
543 case css::property_function_t::rgb:
546 case css::property_function_t::rgba:
549 case css::property_function_t::hsl:
552 case css::property_function_t::hsla:
555 case css::property_function_t::url:
559 css::parse_error::throw_with(
"function_value: unhandled function '", v,
"'");
564 css::parse_error::throw_with(
"function_value: ')' expected but '", c,
"' found.");
567 skip_comments_and_blanks();
570 template<
typename _Handler>
571 void css_parser<_Handler>::function_rgb(
bool alpha)
577 const uint8_t* plast = p + 2;
584 skip_comments_and_blanks();
592 css::parse_error::throw_with(
"function_rgb: ',' expected but '", c,
"' found.");
595 skip_comments_and_blanks();
602 css::parse_error::throw_with(
"function_rgb: ',' expected but '", c,
"' found.");
605 skip_comments_and_blanks();
607 double alpha_val = parse_double_or_throw();
609 alpha_val = std::clamp(alpha_val, 0.0, 1.0);
610 m_handler.rgba(vals[0], vals[1], vals[2], alpha_val);
613 m_handler.rgb(vals[0], vals[1], vals[2]);
621 const uint8_t* pend = plast + 1;
622 for (; p != pend; ++p)
623 std::cout <<
' ' << (
int)*p;
624 std::cout <<
" )" << std::endl;
628 template<
typename _Handler>
629 void css_parser<_Handler>::function_hsl(
bool alpha)
633 double hue = parse_double_or_throw();
634 hue = std::clamp(hue, 0.0, 360.0);
635 skip_comments_and_blanks();
639 css::parse_error::throw_with(
"function_hsl: ',' expected but '", c,
"' found.");
642 skip_comments_and_blanks();
644 double sat = parse_percent();
645 sat = std::clamp(sat, 0.0, 100.0);
646 skip_comments_and_blanks();
650 css::parse_error::throw_with(
"function_hsl: ',' expected but '", c,
"' found.");
653 skip_comments_and_blanks();
655 double light = parse_percent();
656 light = std::clamp(light, 0.0, 100.0);
657 skip_comments_and_blanks();
661 m_handler.hsl(hue, sat, light);
667 css::parse_error::throw_with(
"function_hsl: ',' expected but '", c,
"' found.");
670 skip_comments_and_blanks();
672 double alpha_val = parse_double_or_throw();
673 alpha_val = std::clamp(alpha_val, 0.0, 1.0);
674 skip_comments_and_blanks();
675 m_handler.hsla(hue, sat, light, alpha_val);
678 template<
typename _Handler>
679 void css_parser<_Handler>::function_url()
683 if (c ==
'"' || c ==
'\'')
690 skip_comments_and_blanks();
691 m_handler.url(p, len);
693 std::cout <<
"url(" << std::string(p, len) <<
")" << std::endl;
701 skip_to_or_blank(p, len, ORCUS_ASCII(
")"));
702 skip_comments_and_blanks();
703 m_handler.url(p, len);
705 std::cout <<
"url(" << std::string(p, len) <<
")" << std::endl;
709 template<
typename _Handler>
710 void css_parser<_Handler>::name_sep()
712 assert(cur_char() ==
',');
714 std::cout <<
"," << std::endl;
718 m_handler.end_selector();
721 template<
typename _Handler>
722 void css_parser<_Handler>::property_sep()
725 std::cout <<
";" << std::endl;
728 skip_comments_and_blanks();
731 template<
typename _Handler>
732 void css_parser<_Handler>::block()
736 assert(cur_char() ==
'{');
738 std::cout <<
"{" << std::endl;
740 m_handler.end_selector();
741 m_handler.begin_block();
744 skip_comments_and_blanks();
750 if (cur_char() !=
';')
753 if (cur_char() ==
'}')
758 if (cur_char() !=
'}')
759 throw css::parse_error(
"block: '}' expected.");
761 m_handler.end_block();
764 skip_comments_and_blanks();
767 std::cout <<
"}" << std::endl;
Definition: css_parser_base.hpp:32
Definition: css_parser.hpp:33
void end_parse()
Definition: css_parser.hpp:167
void end_block()
Definition: css_parser.hpp:179
void hsl(uint8_t hue, uint8_t sat, uint8_t light)
Definition: css_parser.hpp:129
void value(const char *p, size_t n)
Definition: css_parser.hpp:91
void end_property()
Definition: css_parser.hpp:189
void begin_parse()
Definition: css_parser.hpp:162
void begin_block()
Definition: css_parser.hpp:173
void url(const char *p, size_t n)
Definition: css_parser.hpp:154
void rgba(uint8_t red, uint8_t green, uint8_t blue, double alpha)
Definition: css_parser.hpp:117
void property_name(const char *p, size_t n)
Definition: css_parser.hpp:80
void rgb(uint8_t red, uint8_t green, uint8_t blue)
Definition: css_parser.hpp:103
void begin_property()
Definition: css_parser.hpp:184
void hsla(uint8_t hue, uint8_t sat, uint8_t light, double alpha)
Definition: css_parser.hpp:143
Definition: css_parser.hpp:194
Definition: parser_base.hpp:41