_lexer =& $lexer; } function add_error(&$error) { $this->_errors[] =& $error; } function get_errors() { return $this->_errors; } function expect($expected_tokens, $skip_mode) { foreach ($expected_tokens as $expected_token) { if ($this->_current_token['code'] === $expected_token['code'] && (!isset($expected_token['value']) || $this->_current_token['value'] === $expected_token['value'])) { return true; }; }; $line = $this->_current_token['line']; $skipped_content = $this->skip_by_mode($skip_mode); $this->error_expected($line, $expected_tokens, $skipped_content); $this->get_next_token(); return false; } function skip_by_mode($skip_mode) { $skipped_content = $this->_current_token['value']; switch ($skip_mode) { case SKIP_TO_SEMICOLON: $skipped_content .= $this->skip_to(CSS_TOKEN_SEMICOLON); break; case SKIP_TO_BLOCK: $skipped_content .= $this->skip_to(CSS_TOKEN_LBRACE); $skipped_content .= $this->skip_to(CSS_TOKEN_RBRACE); break; case SKIP_TO_SEMICOLON_OR_BLOCK: $skipped_content .= $this->skip_to(array(CSS_TOKEN_LBRACE, CSS_TOKEN_SEMICOLON)); if ($this->_current_token['code'] == CSS_TOKEN_LBRACE) { $this->get_next_token(); $skipped_content .= $this->skip_to(array(CSS_TOKEN_RBRACE)); }; break; case SKIP_TO_BLOCK_END: $skipped_content .= $this->skip_to(CSS_TOKEN_RBRACE); break; default: die('Invalid value passed to skip_by_mode'); }; return $skipped_content; } function error_expected($line, $expected_tokens, $skipped_content) { $error =& new CSSParserError($line, $this->_lexer->get_token_context_before(), $this->_lexer->get_token_context_after(), $skipped_content); $this->add_error($error); } function get_next_token() { do { $this->_current_token = $this->_lexer->next_token(); } while ($this->_current_token['code'] === CSS_TOKEN_COMMENT); return $this->_current_token; } function &get_context() { return $this->_context[0]; } function parse() { $this->_context = array(); $this->_errors = array(); $this->get_next_token(); while (!$this->rule_stylesheet()) { // Empty loop; error handling done inside the rule_stylesheet1 }; return true; } function parse_ruleset() { $this->_context = array(); $this->push_context(new CSSStylesheetRuleset()); $this->get_next_token(); if (!$this->rule_ruleset()) { return false; }; return true; } function push_context(&$item) { $this->_context[] =& $item; } function &peek_context() { if (count($this->_context) == 0) { $null = null; return $null; }; return $this->_context[count($this->_context) - 1]; } function &pop_context() { $item =& $this->peek_context(); array_pop($this->_context); return $item; } function rule_stylesheet() { $this->push_context(new CSSStylesheet()); if ($this->_current_token['code'] === CSS_TOKEN_SPACE) { if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_stylesheet1()) { return false; }; } else { if (!$this->rule_stylesheet1()) { return false; }; }; return true; } function rule_stylesheet1() { if ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@charset') { // :: ATKEYWORD["@charset"] STRING SEMICOLON (*) $this->get_next_token(); $this->rule_s_seq_empty(); if (!$this->expect(array(array('code' => CSS_TOKEN_STRING)), SKIP_TO_SEMICOLON_OR_BLOCK)) { return false; }; //* $charset_name = $this->_current_token['value']; $this->get_next_token(); $this->rule_s_seq_empty(); if (!$this->expect(array(array('code' => CSS_TOKEN_SEMICOLON)), SKIP_TO_SEMICOLON_OR_BLOCK)) { return false; }; $this->get_next_token(); // * $stylesheet =& $this->peek_context(); $stylesheet->set_charset($charset_name); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; if (!$this->rule_stylesheet2()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && in_array($this->_current_token['value'], array('@import', '@media', '@page')) || $this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_IDENT, CSS_TOKEN_LBRACK, CSS_TOKEN_SPACE, null))) { // :: if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; if (!$this->rule_stylesheet2()) { return false; }; } else { $this->error_expected($this->_current_token['line'], array(/* todo */), $this->skip_by_mode(SKIP_TO_SEMICOLON_OR_BLOCK)); $this->get_next_token(); return false; }; return true; } function rule_stylesheet2() { if ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@import') { // :: // * $this->push_context(new CSSStylesheetImport); if (!$this->rule_import()) { $this->pop_context(); return false; }; // * $import =& $this->pop_context(); $stylesheet =& $this->peek_context(); $stylesheet->add_import($import); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; if (!$this->rule_stylesheet2()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && in_array($this->_current_token['value'], array('@media', '@page')) || $this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_IDENT, CSS_TOKEN_LBRACK, null))) { // :: if (!$this->rule_stylesheet3()) { return false; }; } else { if (is_null($this->skip_to(CSS_TOKEN_LBRACE))) { return false; }; $this->get_next_token(); if (is_null($this->skip_to(CSS_TOKEN_RBRACE))) { return false; }; $this->get_next_token(); if (!$this->rule_stylesheet2()) { return false; }; }; return true; } function rule_stylesheet3() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_IDENT, CSS_TOKEN_LBRACK))) { // :: // * $this->push_context(new CSSStylesheetRuleset()); if (!$this->rule_ruleset()) { $this->pop_context(); if (is_null($this->skip_to(CSS_TOKEN_RBRACE))) { return false; }; $this->get_next_token(); } else { // * $ruleset =& $this->pop_context(); $stylesheet =& $this->peek_context(); $stylesheet->add_ruleset($ruleset); }; if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; if (!$this->rule_stylesheet3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@media') { // :: // * $this->push_context(new CSSSTylesheetMedia()); if (!$this->rule_media()) { $this->pop_context(); return false; }; // * $media =& $this->pop_context(); $stylesheet =& $this->peek_context(); $stylesheet->add_media($media); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; if (!$this->rule_stylesheet3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@page') { // :: // * $this->push_context(new CSSStylesheetPage()); if (!$this->rule_page()) { $this->pop_context(); return false; }; // * $page =& $this->pop_context(); $stylesheet =& $this->peek_context(); $stylesheet->add_page($page); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; if (!$this->rule_stylesheet3()) { return false; }; } elseif ($this->_current_token['code'] === null) { // :: } else { if (is_null($this->skip_to(CSS_TOKEN_LBRACE))) { return false; }; $this->get_next_token(); if (is_null($this->skip_to(CSS_TOKEN_RBRACE))) { return false; }; $this->get_next_token(); if (!$this->rule_stylesheet2()) { return false; }; }; return true; } function rule_import() { if ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@import') { // :: ATKEYWORD["@import"] $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_import2()) { return false; }; } else { return false; }; return true; } function rule_import2() { if ($this->_current_token['code'] === CSS_TOKEN_STRING) { // :: STRING // * $url = $this->_current_token['value']; $import =& $this->peek_context(); $import->set_url($url); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_import3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_URI) { // :: URI // * $url = $this->_current_token['value']; $import =& $this->peek_context(); $import->set_url($url); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_import3()) { return false; }; } else { return false; }; return true; } function rule_import3() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: if (!$this->rule_medium_seq()) { return false; }; if (!$this->rule_import4()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_SEMICOLON) { // :: if (!$this->rule_import4()) { return false; }; } else { return false; }; return true; } function rule_import4() { if ($this->_current_token['code'] === CSS_TOKEN_SEMICOLON) { // :: SEMICOLON $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_media() { if ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@media') { // :: ATKEYWORD["@media"] LBRACE RBRACE $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_medium_seq()) { return false; }; if ($this->_current_token['code'] !== CSS_TOKEN_LBRACE) { return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetRulesetCollection()); if (!$this->rule_ruleset_seq_empty()) { $this->pop_context(); return false; }; // * $ruleset_collection =& $this->pop_context(); $media =& $this->peek_context(); $media->add_rulesets($ruleset_collection); if ($this->_current_token['code'] !== CSS_TOKEN_RBRACE) { return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_medium() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: IDENT // * $medium_name = $this->_current_token['value']; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $context =& $this->peek_context(); $context->add_medium($medium_name); } else { return false; }; return true; } function rule_page() { if ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && $this->_current_token['value'] === '@page') { // :: ATKEYWORD["@page"] $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_page2()) { return false; }; } else { return false; }; return true; } function rule_page2() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === ':') { // :: DELIM[":"] IDENT $this->get_next_token(); if ($this->_current_token['code'] !== CSS_TOKEN_IDENT) { return false; }; // * $page_name = $this->_current_token['value']; $page =& $this->peek_context(); $page->set_name($page_name); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_page3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_LBRACE) { // :: if (!$this->rule_page3()) { return false; }; } else { return false; }; return true; } function rule_page3() { if ($this->_current_token['code'] === CSS_TOKEN_LBRACE) { // :: LBRACE RBRACE $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetDeclarationCollection()); if (!$this->rule_declaration_seq()) { $this->pop_context(); return false; }; if ($this->_current_token['code'] !== CSS_TOKEN_RBRACE) { $this->pop_context(); return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { $this->pop_context(); return false; }; // * $declarations =& $this->pop_context(); $page =& $this->peek_context(); $page->add_declarations($declarations); } else { return false; }; return true; } function rule_operator() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === '/') { // :: DELIM["/"] $this->get_next_token(); // * $operator =& $this->peek_context(); $operator->set_type(OPERATOR_SLASH); if (!$this->rule_s_seq_empty()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === ',') { // :: DELIM[","] $this->get_next_token(); // * $operator =& $this->peek_context(); $operator->set_type(OPERATOR_COMMA); if (!$this->rule_s_seq_empty()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('-', '+')) || in_array($this->_current_token['code'], array(CSS_TOKEN_NUMBER, CSS_TOKEN_PERCENTAGE, CSS_TOKEN_DIMENSION, CSS_TOKEN_STRING, CSS_TOKEN_IDENT, CSS_TOKEN_URI, CSS_TOKEN_HASH, CSS_TOKEN_FUNCTION))) { // :: // * $operator =& $this->peek_context(); $operator->set_type(OPERATOR_EMPTY); } else { return false; }; return true; } function rule_combinator() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === '+') { // :: DELIM["+"] $this->get_next_token(); // * $operator =& $this->peek_context(); $operator->set_type(COMBINATOR_PLUS); if (!$this->rule_s_seq_empty()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === '>') { // :: DELIM[">"] $this->get_next_token(); // * $operator =& $this->peek_context(); $operator->set_type(COMBINATOR_GREATER); if (!$this->rule_s_seq_empty()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('*', '.', ':')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_LBRACK, CSS_TOKEN_IDENT))) { // :: // * $operator =& $this->peek_context(); $operator->set_type(COMBINATOR_EMPTY); } else { return false; }; return true; } function rule_unary_operator() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === '+') { // :: DELIM["-"] $this->get_next_token(); // * $operator =& $this->peek_context(); $operator->set_type(UNARY_OPERATOR_PLUS); } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && $this->_current_token['value'] === '-') { // :: DELIM["+"] $this->get_next_token(); // * $operator =& $this->peek_context(); $operator->set_type(UNARY_OPERATOR_MINUS); } else { return false; }; return true; } function rule_property() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: IDENT // * $property_name =& $this->_current_token['value']; $property =& $this->peek_context(); $property->set_name($property_name); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_ruleset() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_IDENT, CSS_TOKEN_LBRACE))) { // :: LBRACE RBRACE // * $this->push_context(new CSSStylesheetSelectorCollection()); if (!$this->rule_selector_seq()) { $this->pop_context(); $this->skip_to(CSS_TOKEN_LBRACE); $this->get_next_token(); return false; }; // * $selectors =& $this->pop_context(); $ruleset =& $this->peek_context(); $ruleset->add_selectors($selectors); if ($this->_current_token['code'] !== CSS_TOKEN_LBRACE) { return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetDeclarationCollection()); if (!$this->rule_declaration_seq()) { $this->pop_context(); return false; }; // * $declarations =& $this->pop_context(); $ruleset =& $this->peek_context(); $ruleset->add_declarations($declarations); if ($this->_current_token['code'] !== CSS_TOKEN_RBRACE) { return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_selector() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_IDENT, CSS_TOKEN_LBRACE))) { // :: // * $this->push_context(new CSSStylesheetSimpleSelector); if (!$this->rule_simple_selector()) { $this->pop_context(); return false; }; // * $simple_selector =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_selector($simple_selector); if (!$this->rule_selector2()) { return false; }; } else { return false; }; return true; } function rule_selector2() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('+', '>', '*', '.', ':')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_LBRACK, CSS_TOKEN_IDENT))) { // :: // * $this->push_context(new CSSStylesheetCombinator); if (!$this->rule_combinator()) { return false; }; // * $combinator =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_combinator($combinator); // * $this->push_context(new CSSStylesheetSimpleSelector); if (!$this->rule_simple_selector()) { $this->pop_context(); return false; }; // * $simple_selector =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_selector($simple_selector); if (!$this->rule_selector2()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array(',')) || in_array($this->_current_token['code'], array(CSS_TOKEN_LBRACE))) { // :: } else { return false; }; return true; } function rule_simple_selector() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_IDENT))) { // :: if (!$this->rule_element_name()) { return false; }; if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_LBRACK))) { // :: if (!$this->rule_simple_selector2()) { return false; }; } else { return false; }; return true; } function rule_simple_selector2() { if ($this->_current_token['code'] === CSS_TOKEN_HASH) { // :: HASH // * $selector =& $this->peek_context(); $selector->add_id($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.'))) { // :: if (!$this->rule_class()) { return false; }; if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_LBRACK) { // :: // * $this->push_context(new CSSStylesheetAttrib()); if (!$this->rule_attrib()) { $this->pop_context(); return false; }; // * $attrib =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_attrib($attrib); if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array(':'))) { // :: // * $this->push_context(new CSSStylesheetPseudo()); if (!$this->rule_pseudo()) { $this->pop_context(); return false; }; // * $pseudo =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_pseudo($pseudo); if (!$this->rule_simple_selector3()) { return false; }; } else { return false; }; return true; } function rule_simple_selector3() { if ($this->_current_token['code'] === CSS_TOKEN_HASH) { // :: HASH // * $selector =& $this->peek_context(); $selector->add_id($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.'))) { // :: if (!$this->rule_class()) { return false; }; if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_LBRACK) { // :: // * $this->push_context(new CSSStylesheetAttrib()); if (!$this->rule_attrib()) { $this->pop_context(); return false; }; // * $attrib =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_attrib($attrib); if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array(':'))) { // :: // * $this->push_context(new CSSStylesheetPseudo()); if (!$this->rule_pseudo()) { $this->pop_context(); return false; }; // * $pseudo =& $this->pop_context(); $selector =& $this->peek_context(); $selector->add_pseudo($pseudo); if (!$this->rule_simple_selector3()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('+', '>', ',')) || in_array($this->_current_token['code'], array(CSS_TOKEN_SPACE, CSS_TOKEN_LBRACE))) { // :: $this->rule_s_seq_empty(); } else { return false; }; return true; } function rule_class() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.'))) { // :: DELIM["."] IDENT $this->get_next_token(); if ($this->_current_token['code'] !== CSS_TOKEN_IDENT) { return false; }; // * $selector =& $this->peek_context(); $selector->add_class($this->_current_token['value']); $this->get_next_token(); } else { return false; }; return true; } function rule_element_name() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: IDENT // * $selector =& $this->peek_context(); $selector->set_element($this->_current_token['value']); $this->get_next_token(); } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('*'))) { // :: DELIM["*"] // * $selector =& $this->peek_context(); $selector->set_element('*'); $this->get_next_token(); } else { return false; }; return true; } function rule_attrib() { if ($this->_current_token['code'] === CSS_TOKEN_LBRACK) { // :: LBRACK IDENT $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if ($this->_current_token['code'] !== CSS_TOKEN_IDENT) { return false; }; // * $attrib =& $this->peek_context(); $attrib->set_name($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_attrib2()) { return false; }; } else { return false; }; return true; } function rule_attrib2() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('=')) || in_array($this->_current_token['code'], array(CSS_TOKEN_INCLUDES, CSS_TOKEN_DASHMATCH))) { // :: RBRACK if (!$this->rule_attrib_op()) { return false; }; if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_attrib_value()) { return false; }; if (!$this->rule_s_seq_empty()) { return false; }; if ($this->_current_token['code'] !== CSS_TOKEN_RBRACK) { return false; }; $this->get_next_token(); } elseif ($this->_current_token['code'] == CSS_TOKEN_RBRACK) { // :: RBRACK $this->get_next_token(); } else { return false; } return true; } function rule_pseudo() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array(':'))) { // :: DELIM[":"] $this->get_next_token(); if (!$this->rule_pseudo2()) { return false; }; } else { return false; } return true; } function rule_pseudo2() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: IDENT // * $pseudo =& $this->peek_context(); $pseudo->set_name($this->_current_token['value']); $this->get_next_token(); } elseif ($this->_current_token['code'] === CSS_TOKEN_FUNCTION) { // :: FUNCTION // * $pseudo =& $this->peek_context(); $pseudo->set_function_name($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_pseudo3()) { return false; }; } else { return false; } return true; } function rule_pseudo3() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: IDENT RPAREN // * $pseudo =& $this->peek_context(); $pseudo->set_function_param($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if ($this->_current_token['code'] !== CSS_TOKEN_RPAREN) { return false; }; $this->get_next_token(); } elseif ($this->_current_token['code'] === CSS_TOKEN_SPACE) { // :: RPAREN if (!$this->rule_s_seq_empty()) { return false; }; if ($this->_current_token['code'] !== CSS_TOKEN_RPAREN) { return false; }; $this->get_next_token(); } else { return false; } return true; } function rule_declaration() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: DELIM[":"] // * $this->push_context(new CSSStylesheetProperty()); if (!$this->rule_property()) { $this->pop_context(); return false; }; // * $property =& $this->pop_context(); $declaration =& $this->peek_context(); $declaration->set_property($property); if ($this->_current_token['code'] !== CSS_TOKEN_DELIM || $this->_current_token['value'] !== ':') { return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetExpr()); if (!$this->rule_expr()) { $this->pop_context(); return false; }; // * $expr =& $this->pop_context(); $declaration =& $this->peek_context(); $declaration->set_expr($expr); if (!$this->rule_declaration2()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_SEMICOLON, CSS_TOKEN_RBRACE))) { // :: } else { return false; }; return true; } function rule_declaration2() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('!'))) { // :: if (!$this->rule_prio()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_SEMICOLON, CSS_TOKEN_RBRACE))) { // :: } else { return false; }; return true; } function rule_prio() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('!'))) { // :: DELIM["!"] IDENT["important"] $this->get_next_token(); if ($this->_current_token['code'] !== CSS_TOKEN_IDENT || $this->_current_token['value'] !== 'important') { return false; }; // * $declaration =& $this->peek_context(); $declaration->set_important(true); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_expr() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('-', '+')) || in_array($this->_current_token['code'], array(CSS_TOKEN_NUMBER, CSS_TOKEN_PERCENTAGE, CSS_TOKEN_DIMENSION, CSS_TOKEN_STRING, CSS_TOKEN_IDENT, CSS_TOKEN_URI, CSS_TOKEN_HASH, CSS_TOKEN_FUNCTION))) { // :: // * $this->push_context(new CSSStylesheetTerm()); if (!$this->rule_term()) { $this->pop_context(); return false; }; // * $term =& $this->pop_context(); $expr =& $this->peek_context(); $expr->add_term($term); if (!$this->rule_expr2()) { return false; }; } else { return false; }; return true; } function rule_expr2() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('-', '+', '/', ',')) || in_array($this->_current_token['code'], array(CSS_TOKEN_NUMBER, CSS_TOKEN_PERCENTAGE, CSS_TOKEN_DIMENSION, CSS_TOKEN_STRING, CSS_TOKEN_IDENT, CSS_TOKEN_URI, CSS_TOKEN_HASH, CSS_TOKEN_FUNCTION))) { // :: // * $this->push_context(new CSSStylesheetOperator()); if (!$this->rule_operator()) { $this->pop_context(); return false; }; // * $operator =& $this->pop_context(); $expr =& $this->peek_context(); $expr->add_operator($operator); // * $this->push_context(new CSSStylesheetTerm()); if (!$this->rule_term()) { $this->pop_context(); return false; }; // * $term =& $this->pop_context(); $expr =& $this->peek_context(); $expr->add_term($term); if (!$this->rule_expr2()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('!')) || in_array($this->_current_token['code'], array(CSS_TOKEN_SEMICOLON, CSS_TOKEN_RBRACE, CSS_TOKEN_RPAREN))) { // :: } else { return false; }; return true; } function rule_term() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('-', '+'))) { // :: // * $this->push_context(new CSSStylesheetUnaryOperator()); if (!$this->rule_unary_operator()) { $this->pop_context(); return false; }; // * $operator =& $this->pop_context(); $term =& $this->peek_context(); $term->set_unary_operator($operator); if (!$this->rule_term2()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_NUMBER, CSS_TOKEN_PERCENTAGE, CSS_TOKEN_DIMENSION))) { // :: if (!$this->rule_term2()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_STRING))) { // :: STRING // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_IDENT))) { // :: IDENT // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_URI))) { // :: URI // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_HASH))) { // :: if (!$this->rule_hexcolor()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_FUNCTION))) { // :: if (!$this->rule_function()) { return false; }; } else { return false; }; return true; } function rule_term2() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_NUMBER))) { // :: NUMBER // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_PERCENTAGE))) { // :: PERCENTAGE // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_DIMENSION))) { // :: DIMENSION // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_function() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_FUNCTION))) { // :: FUNCTION RPAREN // * $term =& $this->peek_context(); $term->set_function_name($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetExpr()); if (!$this->rule_expr()) { $this->pop_context(); return false; }; // * $expr =& $this->pop_context(); $term =& $this->peek_context(); $term->set_function_param($expr); if ($this->_current_token['code'] !== CSS_TOKEN_RPAREN) { return false; }; $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_hexcolor() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_HASH))) { // :: HASH // * $term =& $this->peek_context(); $term->set_value($this->_current_token['value']); $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_s_cdo_cdc_seq() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_SPACE))) { // :: SPACE $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_CDO))) { // :: CDO $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_CDC))) { // :: CDC $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_s_cdo_cdc_seq_empty() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_SPACE))) { // :: SPACE $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_CDO))) { // :: CDO $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_CDC))) { // :: CDC $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_CDC))) { // :: CDC $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } elseif ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD && in_array($this->_current_token['value'], array('@import', '@media', '@page')) || $this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_LBRACK, CSS_TOKEN_IDENT, null))) { // :: } elseif ($this->_current_token['code'] === CSS_TOKEN_ATKEYWORD) { // Handle syntax error: invalid @keyword if (!$this->skip_to(array(CSS_TOKEN_LBRACE, CSS_TOKEN_SEMICOLON))) { return false; }; if ($this->_current_token['code'] == CSS_TOKEN_LBRACE) { $this->get_next_token(); if (is_null($this->skip_to(array(CSS_TOKEN_RBRACE)))) { return false; }; }; $this->get_next_token(); if (!$this->rule_s_cdo_cdc_seq_empty()) { return false; }; } else { return false; }; return true; } function rule_s_seq_empty() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_SPACE))) { // :: SPACE $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; } else { // :: return true; }; return true; } function rule_medium_seq() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_IDENT))) { // :: if (!$this->rule_medium()) { return false; }; if (!$this->rule_medium_seq_end()) { return false; }; } else { return false; }; return true; } function rule_medium_seq_end() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array(','))) { // :: DELIM[","] $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; if (!$this->rule_medium()) { return false; }; if (!$this->rule_medium_seq_end()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_SEMICOLON, CSS_TOKEN_LBRACE, CSS_TOKEN_SPACE))) { // :: $this->rule_s_seq_empty(); } else { return false; }; return true; } function rule_ruleset_seq_empty() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_LBRACK, CSS_TOKEN_IDENT))) { // :: // * $this->push_context(new CSSStylesheetRuleset()); if (!$this->rule_ruleset()) { $this->pop_context(); if (is_null($this->skip_to(CSS_TOKEN_RBRACE))) { return false; }; $this->get_next_token(); } else { // * $ruleset =& $this->pop_context(); $ruleset_collection =& $this->peek_context(); $ruleset_collection->add($ruleset); }; if (!$this->rule_ruleset_seq_empty()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_RBRACE))) { // :: } else { return false; }; return true; } function rule_declaration_seq() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_IDENT, CSS_TOKEN_SEMICOLON, CSS_TOKEN_RBRACE))) { // :: // * $this->push_context(new CSSStylesheetDeclaration()); while (!$this->rule_declaration()) { $this->pop_context(); $this->push_context(new CSSStylesheetDeclaration()); if (is_null($this->skip_to(CSS_TOKEN_SEMICOLON))) { $this->pop_context(); return false; }; }; // * $declaration =& $this->pop_context(); $declaration_collection =& $this->peek_context(); $declaration_collection->add($declaration); if (!$this->rule_declaration_seq_end()) { return false; }; } else { return false; }; return true; } function rule_declaration_seq_end() { if (in_array($this->_current_token['code'], array(CSS_TOKEN_SEMICOLON))) { // :: SEMICOLON $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetDeclaration()); while (!$this->rule_declaration()) { $this->pop_context(); $this->push_context(new CSSStylesheetDeclaration()); if (is_null($this->skip_to(CSS_TOKEN_SEMICOLON))) { $this->pop_context(); return false; }; }; // * $declaration =& $this->pop_context(); $declaration_collection =& $this->peek_context(); $declaration_collection->add($declaration); if (!$this->rule_declaration_seq_end()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_RBRACE))) { // :: } else { return false; }; return true; } function rule_selector_seq() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('.', ':', '*')) || in_array($this->_current_token['code'], array(CSS_TOKEN_HASH, CSS_TOKEN_LBRACK, CSS_TOKEN_IDENT))) { // :: // * $this->push_context(new CSSStylesheetSelector()); if (!$this->rule_selector()) { $this->pop_context(); return false; }; // * $selector =& $this->pop_context(); $selector_collection =& $this->peek_context(); $selector_collection->add($selector); if (!$this->rule_selector_seq_end()) { return false; }; } else { return false; }; return true; } function rule_selector_seq_end() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array(','))) { // :: DELIM[","] $this->get_next_token(); if (!$this->rule_s_seq_empty()) { return false; }; // * $this->push_context(new CSSStylesheetSelector()); if (!$this->rule_selector()) { return false; }; // * $selector =& $this->pop_context(); $selector_collection =& $this->peek_context(); $selector_collection->add($selector); if (!$this->rule_selector_seq_end()) { return false; }; } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_LBRACE))) { // :: } else { return false; }; return true; } function rule_attrib_op() { if ($this->_current_token['code'] === CSS_TOKEN_DELIM && in_array($this->_current_token['value'], array('='))) { // :: DELIM["="] // * $attrib =& $this->peek_context(); $attrib->set_op(ATTRIB_OP_EQUAL); $this->get_next_token(); } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_INCLUDES))) { // :: INCLUDES // * $attrib =& $this->peek_context(); $attrib->set_op(ATTRIB_OP_INCLUDES); $this->get_next_token(); } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_DASHMATCH))) { // :: DASHMATCH // * $attrib =& $this->peek_context(); $attrib->set_op(ATTRIB_OP_DASHMATCH); $this->get_next_token(); } else { return false; }; return true; } function rule_attrib_value() { if ($this->_current_token['code'] === CSS_TOKEN_IDENT) { // :: IDENT // * $attrib =& $this->peek_context(); $attrib->set_value($this->_current_token['value']); $this->get_next_token(); } elseif (in_array($this->_current_token['code'], array(CSS_TOKEN_STRING))) { // :: STRING // * $attrib =& $this->peek_context(); $attrib->set_value($this->_current_token['value']); $this->get_next_token(); } else { return false; }; return true; } function skip_to($token_code, $token_value = null) { if (!is_array($token_code)) { $token_code = array($token_code); }; $token_stack = array(); $skipped_content = ''; do { $codes_matched = in_array($this->_current_token['code'], $token_code); $values_matched = $this->_current_token['value'] === $token_value; $value_present = !is_null($token_value); $eof = is_null($this->_current_token['code']); $token_stack_empty = (count($token_stack) == 0); $loop_terminated = $eof || ($codes_matched && ($values_matched || !$value_present) && $token_stack_empty); if (in_array($this->_current_token['code'], array(CSS_TOKEN_LBRACE, CSS_TOKEN_LPAREN, CSS_TOKEN_LBRACK))) { array_unshift($token_stack, $this->_current_token['code']); } elseif ($this->_current_token['code'] === CSS_TOKEN_RBRACE && count($token_stack) > 0 && $token_stack[0] == CSS_TOKEN_LBRACE) { array_shift($token_stack); } elseif ($this->_current_token['code'] === CSS_TOKEN_RPAREN && count($token_stack) > 0 && $token_stack[0] == CSS_TOKEN_LPAREN) { array_shift($token_stack); } elseif ($this->_current_token['code'] === CSS_TOKEN_RBRACK && count($token_stack) > 0 && $token_stack[0] == CSS_TOKEN_LBRACK) { array_shift($token_stack); } if (!$loop_terminated) { $this->get_next_token(); $skipped_content .= $this->_current_token['value']; }; } while (!$loop_terminated); if (is_null($this->_current_token['code'])) { return null; }; return $skipped_content; } } ?>