8#ifndef INCLUDED_ORCUS_CSS_PARSER_HPP
9#define INCLUDED_ORCUS_CSS_PARSER_HPP
11#define ORCUS_DEBUG_CSS 0
13#include "orcus/parser_global.hpp"
14#include "orcus/css_parser_base.hpp"
15#include "orcus/global.hpp"
27template<
typename _Handler>
31 typedef _Handler handler_type;
33 css_parser(
const char* p,
size_t n, handler_type& hdl);
43 void simple_selector_name();
46 void quoted_value(
char c);
48 void function_value(
const char* p,
size_t len);
49 void function_rgb(
bool alpha);
50 void function_hsl(
bool alpha);
56 handler_type& m_handler;
59template<
typename _Handler>
63template<
typename _Handler>
64void css_parser<_Handler>::parse()
69 std::cout <<
"compressed: '";
70 const char* p = mp_char;
71 for (; p != mp_end; ++p)
73 std::cout <<
"'" << std::endl;
75 m_handler.begin_parse();
78 m_handler.end_parse();
81template<
typename _Handler>
82void css_parser<_Handler>::rule()
93 simple_selector_name();
100 set_combinator(c, css::combinator_t::direct_child);
103 set_combinator(c, css::combinator_t::next_sibling);
108 simple_selector_name();
114 reset_before_block();
118 css::parse_error::throw_with(
"rule: failed to parse '", c,
"'");
123template<
typename _Handler>
124void css_parser<_Handler>::at_rule_name()
127 assert(cur_char() ==
'@');
131 throw css::parse_error(
"at_rule_name: first character of an at-rule name must be an alphabet.");
138 m_handler.at_rule_name(p, len);
140 std::string foo(p, len);
141 std::cout <<
"at-rule name: " << foo.c_str() << std::endl;
145template<
typename _Handler>
146void css_parser<_Handler>::simple_selector_name()
157 if (m_simple_selector_count)
160 cout <<
"combinator: " << m_combinator << endl;
162 m_handler.combinator(m_combinator);
163 m_combinator = css::combinator_t::descendant;
165 assert(is_alpha(c) || c ==
'.' || c ==
'#');
167 const char* p =
nullptr;
171 cout <<
"simple_selector_name: (" << m_simple_selector_count <<
")";
174 if (c !=
'.' && c !=
'#')
179 cout <<
" type=" << s;
181 m_handler.simple_selector_type(p, n);
185 while (in_loop && has_char())
193 m_handler.simple_selector_class(p, n);
196 std::cout <<
" class=" << s;
204 m_handler.simple_selector_id(p, n);
207 std::cout <<
" id=" << s;
215 if (cur_char() ==
':')
220 css::pseudo_element_t elem = css::to_pseudo_element(p, n);
222 css::parse_error::throw_with(
223 "selector_name: unknown pseudo element '", p, n,
"'");
225 m_handler.simple_selector_pseudo_element(elem);
231 css::pseudo_class_t pc = css::to_pseudo_class(p, n);
233 css::parse_error::throw_with(
234 "selector_name: unknown pseudo class '", p, n,
"'");
236 m_handler.simple_selector_pseudo_class(pc);
245 m_handler.end_simple_selector();
246 skip_comments_and_blanks();
248 ++m_simple_selector_count;
251 std::cout << std::endl;
255template<
typename _Handler>
256void css_parser<_Handler>::property_name()
262 if (!is_alpha(c) && c !=
'.')
263 css::parse_error::throw_with(
264 "property_name: first character of a name must be an alphabet or a dot, but found '", c,
"'");
269 skip_comments_and_blanks();
271 m_handler.property_name(p, len);
273 std::string foo(p, len);
274 std::cout <<
"property name: " << foo.c_str() << std::endl;
278template<
typename _Handler>
279void css_parser<_Handler>::property()
283 m_handler.begin_property();
285 if (cur_char() !=
':')
286 throw css::parse_error(
"property: ':' expected.");
288 skip_comments_and_blanks();
291 while (in_loop && has_char())
301 skip_comments_and_blanks();
313 skip_comments_and_blanks();
314 m_handler.end_property();
317template<
typename _Handler>
318void css_parser<_Handler>::quoted_value(
char c)
321 const char* p =
nullptr;
327 m_handler.value(p, len);
329 std::string foo(p, len);
330 std::cout <<
"quoted value: " << foo.c_str() << std::endl;
334template<
typename _Handler>
335void css_parser<_Handler>::value()
339 if (c ==
'"' || c ==
'\'')
345 if (!is_alpha(c) && !is_numeric(c) && !is_in(c, ORCUS_ASCII(
"-+.#")))
346 css::parse_error::throw_with(
"value:: illegal first character of a value '", c,
"'");
348 const char* p =
nullptr;
350 identifier(p, len, ORCUS_ASCII(
".%"));
351 if (cur_char() ==
'(')
353 function_value(p, len);
357 m_handler.value(p, len);
359 skip_comments_and_blanks();
362 std::string foo(p, len);
363 std::cout <<
"value: " << foo.c_str() << std::endl;
367template<
typename _Handler>
368void css_parser<_Handler>::function_value(
const char* p,
size_t len)
370 assert(cur_char() ==
'(');
371 css::property_function_t func = css::to_property_function(p, len);
372 if (func == css::property_function_t::unknown)
373 css::parse_error::throw_with(
"function_value: unknown function '", p, len,
"'");
377 skip_comments_and_blanks();
381 case css::property_function_t::rgb:
384 case css::property_function_t::rgba:
387 case css::property_function_t::hsl:
390 case css::property_function_t::hsla:
393 case css::property_function_t::url:
397 css::parse_error::throw_with(
"function_value: unhandled function '", p, len,
"'");
402 css::parse_error::throw_with(
"function_value: ')' expected but '", c,
"' found.");
405 skip_comments_and_blanks();
408template<
typename _Handler>
409void css_parser<_Handler>::function_rgb(
bool alpha)
415 const uint8_t* plast = p + 2;
422 skip_comments_and_blanks();
430 css::parse_error::throw_with(
"function_rgb: ',' expected but '", c,
"' found.");
433 skip_comments_and_blanks();
440 css::parse_error::throw_with(
"function_rgb: ',' expected but '", c,
"' found.");
443 skip_comments_and_blanks();
445 double alpha_val = parse_double_or_throw();
447 alpha_val = clip(alpha_val, 0.0, 1.0);
448 m_handler.rgba(vals[0], vals[1], vals[2], alpha_val);
451 m_handler.rgb(vals[0], vals[1], vals[2]);
459 const uint8_t* pend = plast + 1;
460 for (; p != pend; ++p)
461 std::cout <<
' ' << (
int)*p;
462 std::cout <<
" )" << std::endl;
466template<
typename _Handler>
467void css_parser<_Handler>::function_hsl(
bool alpha)
471 double hue = parse_double_or_throw();
472 hue = clip(hue, 0.0, 360.0);
473 skip_comments_and_blanks();
477 css::parse_error::throw_with(
"function_hsl: ',' expected but '", c,
"' found.");
480 skip_comments_and_blanks();
482 double sat = parse_percent();
483 sat = clip(sat, 0.0, 100.0);
484 skip_comments_and_blanks();
488 css::parse_error::throw_with(
"function_hsl: ',' expected but '", c,
"' found.");
491 skip_comments_and_blanks();
493 double light = parse_percent();
494 light = clip(light, 0.0, 100.0);
495 skip_comments_and_blanks();
499 m_handler.hsl(hue, sat, light);
505 css::parse_error::throw_with(
"function_hsl: ',' expected but '", c,
"' found.");
508 skip_comments_and_blanks();
510 double alpha_val = parse_double_or_throw();
511 alpha_val = clip(alpha_val, 0.0, 1.0);
512 skip_comments_and_blanks();
513 m_handler.hsla(hue, sat, light, alpha_val);
516template<
typename _Handler>
517void css_parser<_Handler>::function_url()
521 if (c ==
'"' || c ==
'\'')
528 skip_comments_and_blanks();
529 m_handler.url(p, len);
531 std::cout <<
"url(" << std::string(p, len) <<
")" << std::endl;
539 skip_to_or_blank(p, len, ORCUS_ASCII(
")"));
540 skip_comments_and_blanks();
541 m_handler.url(p, len);
543 std::cout <<
"url(" << std::string(p, len) <<
")" << std::endl;
547template<
typename _Handler>
548void css_parser<_Handler>::name_sep()
550 assert(cur_char() ==
',');
552 std::cout <<
"," << std::endl;
556 m_handler.end_selector();
559template<
typename _Handler>
560void css_parser<_Handler>::property_sep()
563 std::cout <<
";" << std::endl;
566 skip_comments_and_blanks();
569template<
typename _Handler>
570void css_parser<_Handler>::block()
574 assert(cur_char() ==
'{');
576 std::cout <<
"{" << std::endl;
578 m_handler.end_selector();
579 m_handler.begin_block();
582 skip_comments_and_blanks();
588 if (cur_char() !=
';')
591 if (cur_char() ==
'}')
596 if (cur_char() !=
'}')
597 throw css::parse_error(
"block: '}' expected.");
599 m_handler.end_block();
602 skip_comments_and_blanks();
605 std::cout <<
"}" << std::endl;
Definition: css_parser_base.hpp:31
Definition: css_parser.hpp:29
Definition: parser_base.hpp:40