⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.y

📁 手机浏览器源码程序,功能强大
💻 Y
📖 第 1 页 / 共 2 页
字号:
            CSSSelector *end = $$;
            while( end->tagHistory )
                end = end->tagHistory;
            end->relation = $2;
            end->tagHistory = $1;
            if ( $2 == CSSSelector::Descendant ||
                $2 == CSSSelector::Child ) {
                CSSParser *p = static_cast<CSSParser *>(parser);
                DOM::DocumentImpl *doc = p->document();
                if ( doc )
                    doc->setUsesDescendantRules(true);
            }
            else if ($2 == CSSSelector::Sibling) {
                CSSParser *p = static_cast<CSSParser *>(parser);
                DOM::DocumentImpl *doc = p->document();
                if (doc)
                    doc->setUsesSiblingRules(true);
            }
        } else {
            delete $1;
        }
    }
    | selector error {
        delete $1;
        $$ = 0;
    }
    ;

namespace_selector:
    /* empty */ { $$.string = 0; $$.length = 0; }
    | '*' { static unsigned short star = '*'; $$.string = &star; $$.length = 1; }
    | IDENT { $$ = $1; }
;

simple_selector:
    element_name maybe_space {
	$$ = new CSSSelector();
	$$->tag = $1;
    }
    | element_name specifier_list maybe_space {
	$$ = $2;
	if ( $$ )
            $$->tag = $1;
    }
    | specifier_list maybe_space {
	$$ = $1;
        if ($$)
            $$->tag = makeId(static_cast<CSSParser*>(parser)->defaultNamespace, anyLocalName);;
    }
    | namespace_selector '|' element_name maybe_space {
        $$ = new CSSSelector();
        $$->tag = $3;
        CSSParser *p = static_cast<CSSParser *>(parser);
        if (p->styleElement && p->styleElement->isCSSStyleSheet())
            static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tag, domString($1));
    }
    | namespace_selector '|' element_name specifier_list maybe_space {
        $$ = $4;
        if ($$) {
            $$->tag = $3;
            CSSParser *p = static_cast<CSSParser *>(parser);
            if (p->styleElement && p->styleElement->isCSSStyleSheet())
                static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tag, domString($1));
        }
    }
    | namespace_selector '|' specifier_list maybe_space {
        $$ = $3;
        if ($$) {
            $$->tag = makeId(anyNamespace, anyLocalName);
            CSSParser *p = static_cast<CSSParser *>(parser);
            if (p->styleElement && p->styleElement->isCSSStyleSheet())
                static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tag, domString($1));
        }
    }
  ;

element_name:
    IDENT {
	CSSParser *p = static_cast<CSSParser *>(parser);
	DOM::DocumentImpl *doc = p->document();
	QString tag = qString($1);
	if ( doc ) {
	    if (doc->isHTMLDocument())
		tag = tag.lower();
	    const DOMString dtag(tag);
            $$ = makeId(p->defaultNamespace, doc->tagId(0, dtag.implementation(), false));
	} else {
	    $$ = makeId(p->defaultNamespace, khtml::getTagID(tag.lower().ascii(), tag.length()));
	    // this case should never happen - only when loading
	    // the default stylesheet - which must not contain unknown tags
// 	    assert($$ != 0);
	}
    }
    | '*' {
	$$ = makeId(static_cast<CSSParser*>(parser)->defaultNamespace, anyLocalName);
    }
  ;

specifier_list:
    specifier {
	$$ = $1;
    }
    | specifier_list specifier {
	$$ = $1;
        if ($$) {
            CSSSelector *end = $1;
            while( end->tagHistory )
                end = end->tagHistory;
            end->relation = CSSSelector::SubSelector;
            end->tagHistory = $2;
        }
    }
    | specifier_list error {
        delete $1;
        $$ = 0;
    }
;

specifier:
    HASH {
	$$ = new CSSSelector();
	$$->match = CSSSelector::Id;
	$$->attr = ATTR_ID;
        CSSParser *p = static_cast<CSSParser *>(parser);
        if (!p->strict)
            $1.lower();
	$$->value = atomicString($1);
    }
  | class
  | attrib
  | pseudo
    ;

class:
    '.' IDENT {
        $$ = new CSSSelector();
	$$->match = CSSSelector::Class;
	$$->attr = ATTR_CLASS;
        CSSParser *p = static_cast<CSSParser *>(parser);
        if (!p->strict)
            $2.lower();
	$$->value = atomicString($2);
    }
  ;

attrib_id:
    IDENT maybe_space {
	CSSParser *p = static_cast<CSSParser *>(parser);
	DOM::DocumentImpl *doc = p->document();

	QString attr = qString($1);
	if ( doc ) {
	    if (doc->isHTMLDocument())
		attr = attr.lower();
	    const DOMString dattr(attr);
            $$ = doc->attrId(0, dattr.implementation(), false);
	} else {
	    $$ = khtml::getAttrID(attr.lower().ascii(), attr.length());
	    // this case should never happen - only when loading
	    // the default stylesheet - which must not contain unknown attributes
	    assert($$ != 0);
        }
    }
    ;

attrib:
    '[' maybe_space attrib_id ']' {
	$$ = new CSSSelector();
	$$->attr = $3;
	$$->match = CSSSelector::Set;
    }
    | '[' maybe_space attrib_id match maybe_space ident_or_string maybe_space ']' {
	$$ = new CSSSelector();
	$$->attr = $3;
	$$->match = (CSSSelector::Match)$4;
	$$->value = atomicString($6);
    }
    | '[' maybe_space namespace_selector '|' attrib_id ']' {
        $$ = new CSSSelector();
        $$->attr = $5;
        $$->match = CSSSelector::Set;
        CSSParser *p = static_cast<CSSParser *>(parser);
        if (p->styleElement && p->styleElement->isCSSStyleSheet())
            static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->attr, domString($3));
    }
    | '[' maybe_space namespace_selector '|' attrib_id match maybe_space ident_or_string maybe_space ']' {
        $$ = new CSSSelector();
        $$->attr = $5;
        $$->match = (CSSSelector::Match)$6;
        $$->value = atomicString($8);
        CSSParser *p = static_cast<CSSParser *>(parser);
        if (p->styleElement && p->styleElement->isCSSStyleSheet())
            static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->attr, domString($3));
    }
  ;

match:
    '=' {
	$$ = CSSSelector::Exact;
    }
    | INCLUDES {
	$$ = CSSSelector::List;
    }
    | DASHMATCH {
	$$ = CSSSelector::Hyphen;
    }
    | BEGINSWITH {
	$$ = CSSSelector::Begin;
    }
    | ENDSWITH {
	$$ = CSSSelector::End;
    }
    | CONTAINS {
	$$ = CSSSelector::Contain;
    }
    ;

ident_or_string:
    IDENT
  | STRING
    ;

pseudo:
    ':' IDENT {
        $$ = new CSSSelector();
        $$->match = CSSSelector::Pseudo;
        $2.lower();
        $$->value = atomicString($2);
        if ($$->value == "empty" || $$->value == "only-child" ||
            $$->value == "first-child" || $$->value == "last-child") {
            CSSParser *p = static_cast<CSSParser *>(parser);
            DOM::DocumentImpl *doc = p->document();
            if (doc)
                doc->setUsesSiblingRules(true);
        }
    }
    |
    ':' ':' IDENT {
        $$ = new CSSSelector();
        $$->match = CSSSelector::Pseudo;
        $3.lower();
        $$->value = atomicString($3);
    }
    | ':' FUNCTION maybe_space simple_selector maybe_space ')' {
        $$ = new CSSSelector();
        $$->match = CSSSelector::Pseudo;
        $$->simpleSelector = $4;
        $2.lower();
        $$->value = atomicString($2);
    }
  ;

declaration_list:
    declaration {
	$$ = $1;
    }
    | decl_list declaration {
	$$ = $1;
	if ( $2 )
	    $$ = $2;
    }
    | decl_list {
	$$ = $1;
    }
    | error invalid_block_list error {
	$$ = false;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipping bogus declaration" << endl;
#endif
    }
    | error {
	$$ = false;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipping all declarations" << endl;
#endif
    }
    ;

decl_list:
    declaration ';' maybe_space {
	$$ = $1;
    }
    | declaration invalid_block_list ';' maybe_space {
        $$ = false;
    }
    | error ';' maybe_space {
	$$ = false;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipping bogus declaration" << endl;
#endif
    }
    | error invalid_block_list error ';' maybe_space {
	$$ = false;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipping bogus declaration" << endl;
#endif
    }
    | decl_list declaration ';' maybe_space {
	$$ = $1;
	if ( $2 )
	    $$ = $2;
    }
    | decl_list error ';' maybe_space {
	$$ = $1;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipping bogus declaration" << endl;
#endif
    }
    | decl_list error invalid_block_list error ';' maybe_space {
	$$ = $1;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipping bogus declaration" << endl;
#endif
    }
    ;

declaration:
    property ':' maybe_space expr prio {
	$$ = false;
	CSSParser *p = static_cast<CSSParser *>(parser);
	if ( $1 && $4 ) {
	    p->valueList = $4;
#ifdef CSS_DEBUG
	    kdDebug( 6080 ) << "   got property: " << $1 <<
		($5?" important":"")<< endl;
#endif
	    bool ok = p->parseValue( $1, $5 );
	    if ( ok )
		$$ = ok;
#ifdef CSS_DEBUG
	    else
		kdDebug( 6080 ) << "     couldn't parse value!" << endl;
#endif
	} else {
            delete $4;
        }
	delete p->valueList;
	p->valueList = 0;
    }
    |
    property error {
        $$ = false;
    }
    |
    property ':' maybe_space error expr prio {
        /* The default movable type template has letter-spacing: .none;  Handle this by looking for
        error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
        up and deleting the shifted expr.  */
        delete $5;
        $$ = false;
    }
    |
    prio {
        /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
        $$ = false;
    }
    |
    property ':' maybe_space {
        /* div { font-family: } Just reduce away this property with no value. */
        $$ = false;
    }
  ;

property:
    IDENT maybe_space {
	QString str = qString($1);
	$$ = getPropertyID( str.lower().latin1(), str.length() );
    }
  ;

prio:
    IMPORTANT_SYM maybe_space { $$ = true; }
    | /* empty */ { $$ = false; }
  ;

expr:
    term {
	$$ = new ValueList;
	$$->addValue( $1 );
    }
    | expr operator term {
        $$ = $1;
	if ( $$ ) {
            if ( $2 ) {
                Value v;
                v.id = 0;
                v.unit = Value::Operator;
                v.iValue = $2;
                $$->addValue( v );
            }
            $$->addValue( $3 );
        }
    }
    | expr error {
        delete $1;
        $$ = 0;
    }
  ;

operator:
    '/' maybe_space {
	$$ = '/';
    }
  | ',' maybe_space {
	$$ = ',';
    }
  | /* empty */ {
        $$ = 0;
  }
  ;

term:
  unary_term { $$ = $1; }
  | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
  | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
  | IDENT maybe_space {
      QString str = qString( $1 );
      $$.id = getValueID( str.lower().latin1(), str.length() );
      $$.unit = CSSPrimitiveValue::CSS_IDENT;
      $$.string = $1;
  }
  /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
  | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION }
  | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION }
  | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
  | UNICODERANGE maybe_space { $$.id = 0; $$.iValue = 0; $$.unit = CSSPrimitiveValue::CSS_UNKNOWN;/* ### */ }
  | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; }
  | '#' maybe_space { $$.id = 0; $$.string = ParseString(); $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; } /* Handle error case: "color: #;" */
/* ### according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
  | function {
      $$ = $1;
  }
  ;

unary_term:
  NUMBER maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
  | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
  | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
  | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
  | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
  | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
  | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
  | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
  | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
  | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
  | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
  | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
  | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
  | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
  | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
  | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
  | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = Value::Q_EMS; }
  | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
    ;


function:
  FUNCTION maybe_space expr ')' maybe_space {
      Function *f = new Function;
      f->name = $1;
      f->args = $3;
      $$.id = 0;
      $$.unit = Value::Function;
      $$.function = f;
  } |
  FUNCTION maybe_space error {
      Function *f = new Function;
      f->name = $1;
      f->args = 0;
      $$.id = 0;
      $$.unit = Value::Function;
      $$.function = f;
  }
  ;
/*
 * There is a constraint on the color that it must
 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
 */
hexcolor:
  HASH maybe_space { $$ = $1; }
  ;


/* error handling rules */

invalid_at:
    '@' error invalid_block {
	$$ = 0;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipped invalid @-rule" << endl;
#endif
    }
  | '@' error ';' {
	$$ = 0;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipped invalid @-rule" << endl;
#endif
    }
    ;

invalid_import:
    import {
        delete $1;
        $$ = 0;
#ifdef CSS_DEBUG
        kdDebug( 6080 ) << "skipped invalid import" << endl;
#endif
    }
    ;

invalid_rule:
    error invalid_block {
	$$ = 0;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipped invalid rule" << endl;
#endif
    }
/*
  Seems like the two rules below are trying too much and violating
  http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html

  | error ';' {
	$$ = 0;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipped invalid rule" << endl;
#endif
    }
  | error '}' {
	$$ = 0;
#ifdef CSS_DEBUG
	kdDebug( 6080 ) << "skipped invalid rule" << endl;
#endif
    }
*/
    ;

invalid_block:
    '{' error invalid_block_list error '}'
  | '{' error '}'
    ;

invalid_block_list:
    invalid_block
  | invalid_block_list error invalid_block
;

%%

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -