OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 part of csslib.visitor; |
| 6 |
| 7 ///////////////////////////////////////////////////////////////////////// |
| 8 // CSS specific types: |
| 9 ///////////////////////////////////////////////////////////////////////// |
| 10 |
| 11 class Identifier extends TreeNode { |
| 12 String name; |
| 13 |
| 14 Identifier(this.name, Span span): super(span); |
| 15 |
| 16 visit(VisitorBase visitor) => visitor.visitIdentifier(this); |
| 17 |
| 18 String toString() => name; |
| 19 } |
| 20 |
| 21 class Wildcard extends TreeNode { |
| 22 Wildcard(Span span): super(span); |
| 23 visit(VisitorBase visitor) => visitor.visitWildcard(this); |
| 24 } |
| 25 |
| 26 class ThisOperator extends TreeNode { |
| 27 ThisOperator(Span span): super(span); |
| 28 visit(VisitorBase visitor) => visitor.visitThisOperator(this); |
| 29 } |
| 30 |
| 31 class Negation extends TreeNode { |
| 32 Negation(Span span): super(span); |
| 33 visit(VisitorBase visitor) => visitor.visitNegation(this); |
| 34 } |
| 35 |
| 36 // /* .... */ |
| 37 class CssComment extends TreeNode { |
| 38 final String comment; |
| 39 |
| 40 CssComment(this.comment, Span span): super(span); |
| 41 visit(VisitorBase visitor) => visitor.visitCssComment(this); |
| 42 } |
| 43 |
| 44 // CDO/CDC (Comment Definition Open <!-- and Comment Definition Close -->). |
| 45 class CommentDefinition extends CssComment { |
| 46 CommentDefinition(String comment, Span span): super(comment, span); |
| 47 visit(VisitorBase visitor) => visitor.visitCommentDefinition(this); |
| 48 } |
| 49 |
| 50 class SelectorGroup extends TreeNode { |
| 51 List<Selector> _selectors; |
| 52 |
| 53 SelectorGroup(this._selectors, Span span): super(span); |
| 54 |
| 55 List<Selector> get selectors => _selectors; |
| 56 |
| 57 visit(VisitorBase visitor) => visitor.visitSelectorGroup(this); |
| 58 } |
| 59 |
| 60 class Selector extends TreeNode { |
| 61 final List<SimpleSelectorSequence> _simpleSelectorSequences; |
| 62 |
| 63 Selector(this._simpleSelectorSequences, Span span) : super(span); |
| 64 |
| 65 List<SimpleSelectorSequence> get simpleSelectorSequences => |
| 66 _simpleSelectorSequences; |
| 67 |
| 68 add(SimpleSelectorSequence seq) => _simpleSelectorSequences.add(seq); |
| 69 |
| 70 int get length => _simpleSelectorSequences.length; |
| 71 |
| 72 visit(VisitorBase visitor) => visitor.visitSelector(this); |
| 73 } |
| 74 |
| 75 class SimpleSelectorSequence extends TreeNode { |
| 76 /** +, >, ~, NONE */ |
| 77 final int _combinator; |
| 78 final SimpleSelector _selector; |
| 79 |
| 80 SimpleSelectorSequence(this._selector, Span span, |
| 81 [int combinator = TokenKind.COMBINATOR_NONE]) |
| 82 : _combinator = combinator, super(span); |
| 83 |
| 84 get simpleSelector => _selector; |
| 85 |
| 86 bool get isCombinatorNone => _combinator == TokenKind.COMBINATOR_NONE; |
| 87 bool get isCombinatorPlus => _combinator == TokenKind.COMBINATOR_PLUS; |
| 88 bool get isCombinatorGreater => _combinator == TokenKind.COMBINATOR_GREATER; |
| 89 bool get isCombinatorTilde => _combinator == TokenKind.COMBINATOR_TILDE; |
| 90 bool get isCombinatorDescendant => |
| 91 _combinator == TokenKind.COMBINATOR_DESCENDANT; |
| 92 |
| 93 String get _combinatorToString => |
| 94 isCombinatorDescendant ? ' ' : |
| 95 isCombinatorPlus ? ' + ' : |
| 96 isCombinatorGreater ? ' > ' : |
| 97 isCombinatorTilde ? ' ~ ' : ''; |
| 98 |
| 99 visit(VisitorBase visitor) => visitor.visitSimpleSelectorSequence(this); |
| 100 } |
| 101 |
| 102 /* All other selectors (element, #id, .class, attribute, pseudo, negation, |
| 103 * namespace, *) are derived from this selector. |
| 104 */ |
| 105 class SimpleSelector extends TreeNode { |
| 106 final _name; |
| 107 |
| 108 SimpleSelector(this._name, Span span) : super(span); |
| 109 |
| 110 // Name can be an Identifier or WildCard we'll return either the name or '*'. |
| 111 String get name => isWildcard ? '*' : isThis ? '&' : _name.name; |
| 112 |
| 113 bool get isWildcard => _name is Wildcard; |
| 114 |
| 115 bool get isThis => _name is ThisOperator; |
| 116 |
| 117 visit(VisitorBase visitor) => visitor.visitSimpleSelector(this); |
| 118 } |
| 119 |
| 120 // element name |
| 121 class ElementSelector extends SimpleSelector { |
| 122 ElementSelector(name, Span span) : super(name, span); |
| 123 visit(VisitorBase visitor) => visitor.visitElementSelector(this); |
| 124 } |
| 125 |
| 126 // namespace|element |
| 127 class NamespaceSelector extends SimpleSelector { |
| 128 final _namespace; // null, Wildcard or Identifier |
| 129 |
| 130 NamespaceSelector(this._namespace, var name, Span span) : super(name, span); |
| 131 |
| 132 String get namespace => |
| 133 _namespace is Wildcard ? '*' : _namespace == null ? '' : _namespace.name; |
| 134 |
| 135 bool get isNamespaceWildcard => _namespace is Wildcard; |
| 136 |
| 137 SimpleSelector get nameAsSimpleSelector => _name; |
| 138 |
| 139 visit(VisitorBase visitor) => visitor.visitNamespaceSelector(this); |
| 140 } |
| 141 |
| 142 // [attr op value] |
| 143 class AttributeSelector extends SimpleSelector { |
| 144 final int _op; |
| 145 final _value; |
| 146 |
| 147 AttributeSelector(Identifier name, this._op, this._value, |
| 148 Span span) : super(name, span); |
| 149 |
| 150 String matchOperator() { |
| 151 switch (_op) { |
| 152 case TokenKind.EQUALS: |
| 153 return '='; |
| 154 case TokenKind.INCLUDES: |
| 155 return '~='; |
| 156 case TokenKind.DASH_MATCH: |
| 157 return '|='; |
| 158 case TokenKind.PREFIX_MATCH: |
| 159 return '^='; |
| 160 case TokenKind.SUFFIX_MATCH: |
| 161 return '\$='; |
| 162 case TokenKind.SUBSTRING_MATCH: |
| 163 return '*='; |
| 164 case TokenKind.NO_MATCH: |
| 165 return ''; |
| 166 } |
| 167 } |
| 168 |
| 169 // Return the TokenKind for operator used by visitAttributeSelector. |
| 170 String matchOperatorAsTokenString() { |
| 171 switch (_op) { |
| 172 case TokenKind.EQUALS: |
| 173 return 'EQUALS'; |
| 174 case TokenKind.INCLUDES: |
| 175 return 'INCLUDES'; |
| 176 case TokenKind.DASH_MATCH: |
| 177 return 'DASH_MATCH'; |
| 178 case TokenKind.PREFIX_MATCH: |
| 179 return 'PREFIX_MATCH'; |
| 180 case TokenKind.SUFFIX_MATCH: |
| 181 return 'SUFFIX_MATCH'; |
| 182 case TokenKind.SUBSTRING_MATCH: |
| 183 return 'SUBSTRING_MATCH'; |
| 184 } |
| 185 } |
| 186 |
| 187 String valueToString() { |
| 188 if (_value != null) { |
| 189 if (_value is Identifier) { |
| 190 return _value.name; |
| 191 } else { |
| 192 return '"${_value}"'; |
| 193 } |
| 194 } else { |
| 195 return ''; |
| 196 } |
| 197 } |
| 198 |
| 199 visit(VisitorBase visitor) => visitor.visitAttributeSelector(this); |
| 200 } |
| 201 |
| 202 // #id |
| 203 class IdSelector extends SimpleSelector { |
| 204 IdSelector(Identifier name, Span span) : super(name, span); |
| 205 visit(VisitorBase visitor) => visitor.visitIdSelector(this); |
| 206 } |
| 207 |
| 208 // .class |
| 209 class ClassSelector extends SimpleSelector { |
| 210 ClassSelector(Identifier name, Span span) : super(name, span); |
| 211 visit(VisitorBase visitor) => visitor.visitClassSelector(this); |
| 212 } |
| 213 |
| 214 // :pseudoClass |
| 215 class PseudoClassSelector extends SimpleSelector { |
| 216 PseudoClassSelector(Identifier name, Span span) : super(name, span); |
| 217 visit(VisitorBase visitor) => visitor.visitPseudoClassSelector(this); |
| 218 } |
| 219 |
| 220 // ::pseudoElement |
| 221 class PseudoElementSelector extends SimpleSelector { |
| 222 PseudoElementSelector(Identifier name, Span span) : super(name, span); |
| 223 visit(VisitorBase visitor) => visitor.visitPseudoElementSelector(this); |
| 224 } |
| 225 |
| 226 // :pseudoClassFunction(expression) |
| 227 class PseudoClassFunctionSelector extends PseudoClassSelector { |
| 228 SelectorExpression expression; |
| 229 |
| 230 PseudoClassFunctionSelector(Identifier name, this.expression, Span span) |
| 231 : super(name, span); |
| 232 visit(VisitorBase visitor) => visitor.visitPseudoClassFunctionSelector(this); |
| 233 } |
| 234 |
| 235 // ::pseudoElementFunction(expression) |
| 236 class PseudoElementFunctionSelector extends PseudoElementSelector { |
| 237 SelectorExpression expression; |
| 238 |
| 239 PseudoElementFunctionSelector(Identifier name, this.expression, Span span) |
| 240 : super(name, span); |
| 241 visit(VisitorBase visitor) => |
| 242 visitor.visitPseudoElementFunctionSelector(this); |
| 243 } |
| 244 |
| 245 class SelectorExpression extends TreeNode { |
| 246 final List<Expression> _expressions = []; |
| 247 |
| 248 SelectorExpression(Span span): super(span); |
| 249 |
| 250 add(Expression expression) { |
| 251 _expressions.add(expression); |
| 252 } |
| 253 |
| 254 List<Expression> get expressions => _expressions; |
| 255 |
| 256 visit(VisitorBase visitor) => visitor.visitSelectorExpression(this); |
| 257 } |
| 258 |
| 259 // :NOT(negation_arg) |
| 260 class NegationSelector extends SimpleSelector { |
| 261 SimpleSelector negationArg; |
| 262 |
| 263 NegationSelector(this.negationArg, Span span) |
| 264 : super(new Negation(span), span); |
| 265 |
| 266 visit(VisitorBase visitor) => visitor.visitNegationSelector(this); |
| 267 } |
| 268 |
| 269 class StyleSheet extends TreeNode { |
| 270 /** |
| 271 * Contains charset, ruleset, directives (media, page, etc.), and selectors. |
| 272 */ |
| 273 final topLevels; |
| 274 |
| 275 StyleSheet(this.topLevels, Span span) : super(span) { |
| 276 for (final node in topLevels) { |
| 277 assert(node is TopLevelProduction || node is Directive); |
| 278 } |
| 279 } |
| 280 |
| 281 /** Selectors only in this tree. */ |
| 282 StyleSheet.selector(this.topLevels, Span span) : super(span); |
| 283 |
| 284 visit(VisitorBase visitor) => visitor.visitStyleSheet(this); |
| 285 } |
| 286 |
| 287 class TopLevelProduction extends TreeNode { |
| 288 TopLevelProduction(Span span) : super(span); |
| 289 visit(VisitorBase visitor) => visitor.visitTopLevelProduction(this); |
| 290 } |
| 291 |
| 292 class RuleSet extends TopLevelProduction { |
| 293 final SelectorGroup _selectorGroup; |
| 294 final DeclarationGroup _declarationGroup; |
| 295 |
| 296 RuleSet(this._selectorGroup, this._declarationGroup, Span span) : super(span); |
| 297 |
| 298 SelectorGroup get selectorGroup => _selectorGroup; |
| 299 DeclarationGroup get declarationGroup => _declarationGroup; |
| 300 |
| 301 visit(VisitorBase visitor) => visitor.visitRuleSet(this); |
| 302 } |
| 303 |
| 304 class Directive extends TreeNode { |
| 305 Directive(Span span) : super(span); |
| 306 |
| 307 bool get isBuiltIn => true; // Known CSS directive? |
| 308 bool get isExtension => false; // SCSS extension? |
| 309 |
| 310 visit(VisitorBase visitor) => visitor.visitDirective(this); |
| 311 } |
| 312 |
| 313 class ImportDirective extends Directive { |
| 314 /** import name specified. */ |
| 315 final String import; |
| 316 |
| 317 /** Any media queries for this import. */ |
| 318 final List<MediaQuery> mediaQueries; |
| 319 |
| 320 ImportDirective(this.import, this.mediaQueries, Span span) : super(span); |
| 321 |
| 322 visit(VisitorBase visitor) => visitor.visitImportDirective(this); |
| 323 } |
| 324 |
| 325 /** |
| 326 * MediaExpression grammar: |
| 327 * '(' S* media_feature S* [ ':' S* expr ]? ')' S* |
| 328 */ |
| 329 class MediaExpression extends TreeNode { |
| 330 final bool andOperator; |
| 331 final Identifier _mediaFeature; |
| 332 final Expressions exprs; |
| 333 |
| 334 MediaExpression(this.andOperator, this._mediaFeature, this.exprs, Span span) |
| 335 : super(span); |
| 336 |
| 337 String get mediaFeature => _mediaFeature.name; |
| 338 |
| 339 visit(VisitorBase visitor) => visitor.visitMediaExpression(this); |
| 340 } |
| 341 |
| 342 /** |
| 343 * MediaQuery grammar: |
| 344 * : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]* |
| 345 * | media_expression [ AND S* media_expression ]* |
| 346 * media_type |
| 347 * : IDENT |
| 348 * media_expression |
| 349 * : '(' S* media_feature S* [ ':' S* expr ]? ')' S* |
| 350 * media_feature |
| 351 * : IDENT |
| 352 */ |
| 353 class MediaQuery extends TreeNode { |
| 354 /** not, only or no operator. */ |
| 355 final int _mediaUnary; |
| 356 final Identifier _mediaType; |
| 357 final List<MediaExpression> expressions; |
| 358 |
| 359 MediaQuery(this._mediaUnary, this._mediaType, this.expressions, Span span) |
| 360 : super(span); |
| 361 |
| 362 bool get hasMediaType => _mediaType != null; |
| 363 String get mediaType => _mediaType.name; |
| 364 |
| 365 bool get hasUnary => _mediaUnary != -1; |
| 366 String get unary => |
| 367 TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary).toUpperCase(); |
| 368 |
| 369 visit(VisitorBase visitor) => visitor.visitMediaQuery(this); |
| 370 } |
| 371 |
| 372 class MediaDirective extends Directive { |
| 373 List<MediaQuery> mediaQueries; |
| 374 List<RuleSet> rulesets; |
| 375 |
| 376 MediaDirective(this.mediaQueries, this.rulesets, Span span) : super(span); |
| 377 |
| 378 visit(VisitorBase visitor) => visitor.visitMediaDirective(this); |
| 379 } |
| 380 |
| 381 class HostDirective extends Directive { |
| 382 List<RuleSet> rulesets; |
| 383 |
| 384 HostDirective(this.rulesets, Span span) : super(span); |
| 385 |
| 386 visit(VisitorBase visitor) => visitor.visitHostDirective(this); |
| 387 } |
| 388 |
| 389 class PageDirective extends Directive { |
| 390 final String _ident; |
| 391 final String _pseudoPage; |
| 392 List<DeclarationGroup> _declsMargin; |
| 393 |
| 394 PageDirective(this._ident, this._pseudoPage, this._declsMargin, |
| 395 Span span) : super(span); |
| 396 |
| 397 visit(VisitorBase visitor) => visitor.visitPageDirective(this); |
| 398 |
| 399 bool get hasIdent => _ident != null && _ident.length > 0; |
| 400 bool get hasPseudoPage => _pseudoPage != null && _pseudoPage.length > 0; |
| 401 } |
| 402 |
| 403 class CharsetDirective extends Directive { |
| 404 final String charEncoding; |
| 405 |
| 406 CharsetDirective(this.charEncoding, Span span) : super(span); |
| 407 visit(VisitorBase visitor) => visitor.visitCharsetDirective(this); |
| 408 } |
| 409 |
| 410 class KeyFrameDirective extends Directive { |
| 411 /* |
| 412 * Either @keyframe or keyframe prefixed with @-webkit-, @-moz-, @-ms-, @-o-. |
| 413 */ |
| 414 final int _keyframeName; |
| 415 final _name; |
| 416 final List<KeyFrameBlock> _blocks; |
| 417 |
| 418 KeyFrameDirective(this._keyframeName, this._name, Span span) |
| 419 : _blocks = [], super(span); |
| 420 |
| 421 add(KeyFrameBlock block) { |
| 422 _blocks.add(block); |
| 423 } |
| 424 |
| 425 String get keyFrameName { |
| 426 switch (_keyframeName) { |
| 427 case TokenKind.DIRECTIVE_KEYFRAMES: |
| 428 case TokenKind.DIRECTIVE_MS_KEYFRAMES: |
| 429 return '@keyframes'; |
| 430 case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES: return '@-webkit-keyframes'; |
| 431 case TokenKind.DIRECTIVE_MOZ_KEYFRAMES: return '@-moz-keyframes'; |
| 432 case TokenKind.DIRECTIVE_O_KEYFRAMES: return '@-o-keyframes'; |
| 433 } |
| 434 } |
| 435 |
| 436 String get name => _name; |
| 437 |
| 438 visit(VisitorBase visitor) => visitor.visitKeyFrameDirective(this); |
| 439 } |
| 440 |
| 441 class KeyFrameBlock extends Expression { |
| 442 final Expressions _blockSelectors; |
| 443 final DeclarationGroup _declarations; |
| 444 |
| 445 KeyFrameBlock(this._blockSelectors, this._declarations, Span span) |
| 446 : super(span); |
| 447 |
| 448 visit(VisitorBase visitor) => visitor.visitKeyFrameBlock(this); |
| 449 } |
| 450 |
| 451 class FontFaceDirective extends Directive { |
| 452 final DeclarationGroup _declarations; |
| 453 |
| 454 FontFaceDirective(this._declarations, Span span) : super(span); |
| 455 |
| 456 visit(VisitorBase visitor) => visitor.visitFontFaceDirective(this); |
| 457 } |
| 458 |
| 459 class StyletDirective extends Directive { |
| 460 final String _dartClassName; |
| 461 final List<RuleSet> _rulesets; |
| 462 |
| 463 StyletDirective(this._dartClassName, this._rulesets, Span span) : super(span); |
| 464 |
| 465 bool get isBuiltIn => false; |
| 466 bool get isExtension => true; |
| 467 |
| 468 String get dartClassName => _dartClassName; |
| 469 List<RuleSet> get rulesets => _rulesets; |
| 470 |
| 471 visit(VisitorBase visitor) => visitor.visitStyletDirective(this); |
| 472 } |
| 473 |
| 474 class NamespaceDirective extends Directive { |
| 475 /** Namespace prefix. */ |
| 476 final String _prefix; |
| 477 |
| 478 /** URI associated with this namespace. */ |
| 479 final String _uri; |
| 480 |
| 481 NamespaceDirective(this._prefix, this._uri, Span span) : super(span); |
| 482 |
| 483 visit(VisitorBase visitor) => visitor.visitNamespaceDirective(this); |
| 484 |
| 485 String get prefix => _prefix.length > 0 ? '$_prefix ' : ''; |
| 486 } |
| 487 |
| 488 /** To support Less syntax @name: expression */ |
| 489 class VarDefinitionDirective extends Directive { |
| 490 final VarDefinition def; |
| 491 |
| 492 VarDefinitionDirective(this.def, Span span) : super(span); |
| 493 |
| 494 visit(VisitorBase visitor) => visitor.visitVarDefinitionDirective(this); |
| 495 } |
| 496 |
| 497 class Declaration extends TreeNode { |
| 498 final Identifier _property; |
| 499 final Expression _expression; |
| 500 /** Style exposed to Dart. */ |
| 501 var _dart; |
| 502 final bool important; |
| 503 |
| 504 /** |
| 505 * IE CSS hacks that can only be read by a particular IE version. |
| 506 * 7 implies IE 7 or older property (e.g., *background: blue;) |
| 507 * Note: IE 8 or older property (e.g., background: green\9;) is handled |
| 508 * by IE8Term in declaration expression handling. |
| 509 * Note: IE 6 only property with a leading underscore is a valid IDENT |
| 510 * since an ident can start with underscore (e.g., _background: red;) |
| 511 */ |
| 512 final bool isIE7; |
| 513 |
| 514 Declaration(this._property, this._expression, this._dart, Span span, |
| 515 {important: false, ie7: false}) |
| 516 : this.important = important, this.isIE7 = ie7, super(span); |
| 517 |
| 518 String get property => isIE7 ? '*${_property.name}' : _property.name; |
| 519 Expression get expression => _expression; |
| 520 |
| 521 bool get hasDartStyle => _dart != null; |
| 522 get dartStyle => _dart; |
| 523 set dartStyle(dStyle) { |
| 524 _dart = dStyle; |
| 525 } |
| 526 |
| 527 visit(VisitorBase visitor) => visitor.visitDeclaration(this); |
| 528 } |
| 529 |
| 530 // TODO(terry): Consider 2 kinds of VarDefinitions static at top-level and |
| 531 // dynamic when in a declaration. Currently, Less syntax |
| 532 // '@foo: expression' and 'var-foo: expression' in a declaration |
| 533 // are statically resolved. Better solution, if @foo or var-foo |
| 534 // are top-level are then statically resolved and var-foo in a |
| 535 // declaration group (surrounded by a selector) would be dynamic. |
| 536 class VarDefinition extends Declaration { |
| 537 VarDefinition(Identifier definedName, Expression expr, Span span) |
| 538 : super(definedName, expr, null, span); |
| 539 |
| 540 String get definedName => _property.name; |
| 541 |
| 542 set dartStyle(dStyle) { } |
| 543 |
| 544 visit(VisitorBase visitor) => visitor.visitVarDefinition(this); |
| 545 } |
| 546 |
| 547 class DeclarationGroup extends TreeNode { |
| 548 /** Can be either Declaration or RuleSet (if nested selector). */ |
| 549 final List _declarations; |
| 550 |
| 551 DeclarationGroup(this._declarations, Span span) : super(span); |
| 552 |
| 553 List get declarations => _declarations; |
| 554 |
| 555 visit(VisitorBase visitor) => visitor.visitDeclarationGroup(this); |
| 556 } |
| 557 |
| 558 class MarginGroup extends DeclarationGroup { |
| 559 final int margin_sym; // TokenType for for @margin sym. |
| 560 |
| 561 MarginGroup(this.margin_sym, List<Declaration> decls, Span span) |
| 562 : super(decls, span); |
| 563 visit(VisitorBase visitor) => visitor.visitMarginGroup(this); |
| 564 } |
| 565 |
| 566 class VarUsage extends Expression { |
| 567 final String name; |
| 568 final List<Expression> defaultValues; |
| 569 |
| 570 VarUsage(this.name, this.defaultValues, Span span) : super(span); |
| 571 |
| 572 visit(VisitorBase visitor) => visitor.visitVarUsage(this); |
| 573 } |
| 574 |
| 575 class OperatorSlash extends Expression { |
| 576 OperatorSlash(Span span) : super(span); |
| 577 visit(VisitorBase visitor) => visitor.visitOperatorSlash(this); |
| 578 } |
| 579 |
| 580 class OperatorComma extends Expression { |
| 581 OperatorComma(Span span) : super(span); |
| 582 visit(VisitorBase visitor) => visitor.visitOperatorComma(this); |
| 583 } |
| 584 |
| 585 class OperatorPlus extends Expression { |
| 586 OperatorPlus(Span span) : super(span); |
| 587 visit(VisitorBase visitor) => visitor.visitOperatorPlus(this); |
| 588 } |
| 589 |
| 590 class OperatorMinus extends Expression { |
| 591 OperatorMinus(Span span) : super(span); |
| 592 visit(VisitorBase visitor) => visitor.visitOperatorMinus(this); |
| 593 } |
| 594 |
| 595 class UnicodeRangeTerm extends Expression { |
| 596 final String first; |
| 597 final String second; |
| 598 |
| 599 UnicodeRangeTerm(this.first, this.second, Span span) : super(span); |
| 600 |
| 601 bool get hasSecond => second != null; |
| 602 |
| 603 visit(VisitorBase visitor) => visitor.visitUnicodeRangeTerm(this); |
| 604 } |
| 605 |
| 606 class LiteralTerm extends Expression { |
| 607 // TODO(terry): value and text fields can be made final once all CSS resources |
| 608 // are copied/symlink'd in the build tool and UriVisitor in |
| 609 // web_ui is removed. |
| 610 var value; |
| 611 String text; |
| 612 |
| 613 LiteralTerm(this.value, this.text, Span span) : super(span); |
| 614 |
| 615 visit(VisitorBase visitor) => visitor.visitLiteralTerm(this); |
| 616 } |
| 617 |
| 618 class NumberTerm extends LiteralTerm { |
| 619 NumberTerm(value, String t, Span span) : super(value, t, span); |
| 620 visit(VisitorBase visitor) => visitor.visitNumberTerm(this); |
| 621 } |
| 622 |
| 623 class UnitTerm extends LiteralTerm { |
| 624 final int _unit; |
| 625 |
| 626 UnitTerm(value, String t, Span span, this._unit) : super(value, t, span); |
| 627 |
| 628 int get unit => _unit; |
| 629 |
| 630 visit(VisitorBase visitor) => visitor.visitUnitTerm(this); |
| 631 |
| 632 String unitToString() => TokenKind.unitToString(_unit); |
| 633 |
| 634 String toString() => '$text${unitToString()}'; |
| 635 } |
| 636 |
| 637 class LengthTerm extends UnitTerm { |
| 638 LengthTerm(value, String t, Span span, |
| 639 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 640 assert(this._unit == TokenKind.UNIT_LENGTH_PX || |
| 641 this._unit == TokenKind.UNIT_LENGTH_CM || |
| 642 this._unit == TokenKind.UNIT_LENGTH_MM || |
| 643 this._unit == TokenKind.UNIT_LENGTH_IN || |
| 644 this._unit == TokenKind.UNIT_LENGTH_PT || |
| 645 this._unit == TokenKind.UNIT_LENGTH_PC); |
| 646 } |
| 647 |
| 648 visit(VisitorBase visitor) => visitor.visitLengthTerm(this); |
| 649 } |
| 650 |
| 651 class PercentageTerm extends LiteralTerm { |
| 652 PercentageTerm(value, String t, Span span) : super(value, t, span); |
| 653 visit(VisitorBase visitor) => visitor.visitPercentageTerm(this); |
| 654 } |
| 655 |
| 656 class EmTerm extends LiteralTerm { |
| 657 EmTerm(value, String t, Span span) : super(value, t, span); |
| 658 visit(VisitorBase visitor) => visitor.visitEmTerm(this); |
| 659 } |
| 660 |
| 661 class ExTerm extends LiteralTerm { |
| 662 ExTerm(value, String t, Span span) : super(value, t, span); |
| 663 visit(VisitorBase visitor) => visitor.visitExTerm(this); |
| 664 } |
| 665 |
| 666 class AngleTerm extends UnitTerm { |
| 667 AngleTerm(var value, String t, Span span, |
| 668 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 669 assert(this._unit == TokenKind.UNIT_ANGLE_DEG || |
| 670 this._unit == TokenKind.UNIT_ANGLE_RAD || |
| 671 this._unit == TokenKind.UNIT_ANGLE_GRAD || |
| 672 this._unit == TokenKind.UNIT_ANGLE_TURN); |
| 673 } |
| 674 |
| 675 visit(VisitorBase visitor) => visitor.visitAngleTerm(this); |
| 676 } |
| 677 |
| 678 class TimeTerm extends UnitTerm { |
| 679 TimeTerm(var value, String t, Span span, |
| 680 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 681 assert(this._unit == TokenKind.UNIT_ANGLE_DEG || |
| 682 this._unit == TokenKind.UNIT_TIME_MS || |
| 683 this._unit == TokenKind.UNIT_TIME_S); |
| 684 } |
| 685 |
| 686 visit(VisitorBase visitor) => visitor.visitTimeTerm(this); |
| 687 } |
| 688 |
| 689 class FreqTerm extends UnitTerm { |
| 690 FreqTerm(var value, String t, Span span, |
| 691 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 692 assert(_unit == TokenKind.UNIT_FREQ_HZ || _unit == TokenKind.UNIT_FREQ_KHZ); |
| 693 } |
| 694 |
| 695 visit(VisitorBase visitor) => visitor.visitFreqTerm(this); |
| 696 } |
| 697 |
| 698 class FractionTerm extends LiteralTerm { |
| 699 FractionTerm(var value, String t, Span span) : super(value, t, span); |
| 700 |
| 701 visit(VisitorBase visitor) => visitor.visitFractionTerm(this); |
| 702 } |
| 703 |
| 704 class UriTerm extends LiteralTerm { |
| 705 UriTerm(String value, Span span) : super(value, value, span); |
| 706 |
| 707 visit(VisitorBase visitor) => visitor.visitUriTerm(this); |
| 708 } |
| 709 |
| 710 class ResolutionTerm extends UnitTerm { |
| 711 ResolutionTerm(var value, String t, Span span, |
| 712 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 713 assert(_unit == TokenKind.UNIT_RESOLUTION_DPI || |
| 714 _unit == TokenKind.UNIT_RESOLUTION_DPCM || |
| 715 _unit == TokenKind.UNIT_RESOLUTION_DPPX); |
| 716 } |
| 717 |
| 718 visit(VisitorBase visitor) => visitor.visitResolutionTerm(this); |
| 719 } |
| 720 |
| 721 class ChTerm extends UnitTerm { |
| 722 ChTerm(var value, String t, Span span, |
| 723 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 724 assert(_unit == TokenKind.UNIT_CH); |
| 725 } |
| 726 |
| 727 visit(VisitorBase visitor) => visitor.visitChTerm(this); |
| 728 } |
| 729 |
| 730 class RemTerm extends UnitTerm { |
| 731 RemTerm(var value, String t, Span span, |
| 732 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 733 assert(_unit == TokenKind.UNIT_REM); |
| 734 } |
| 735 |
| 736 visit(VisitorBase visitor) => visitor.visitRemTerm(this); |
| 737 } |
| 738 |
| 739 class ViewportTerm extends UnitTerm { |
| 740 ViewportTerm(var value, String t, Span span, |
| 741 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) { |
| 742 assert(_unit == TokenKind.UNIT_VIEWPORT_VW || |
| 743 _unit == TokenKind.UNIT_VIEWPORT_VH || |
| 744 _unit == TokenKind.UNIT_VIEWPORT_VMIN || |
| 745 _unit == TokenKind.UNIT_VIEWPORT_VMAX); |
| 746 } |
| 747 |
| 748 visit(VisitorBase visitor) => visitor.visitViewportTerm(this); |
| 749 } |
| 750 |
| 751 /** Type to signal a bad hex value for HexColorTerm.value. */ |
| 752 class BAD_HEX_VALUE { } |
| 753 |
| 754 class HexColorTerm extends LiteralTerm { |
| 755 HexColorTerm(var value, String t, Span span) : super(value, t, span); |
| 756 |
| 757 visit(VisitorBase visitor) => visitor.visitHexColorTerm(this); |
| 758 } |
| 759 |
| 760 class FunctionTerm extends LiteralTerm { |
| 761 final Expressions _params; |
| 762 |
| 763 FunctionTerm(var value, String t, this._params, Span span) |
| 764 : super(value, t, span); |
| 765 |
| 766 visit(VisitorBase visitor) => visitor.visitFunctionTerm(this); |
| 767 } |
| 768 |
| 769 /** |
| 770 * A "\9" was encountered at the end of the expression and before a semi-colon. |
| 771 * This is an IE trick to ignore a property or value except by IE 8 and older |
| 772 * browsers. |
| 773 */ |
| 774 class IE8Term extends LiteralTerm { |
| 775 IE8Term(Span span) : super('\\9', '\\9', span); |
| 776 visit(VisitorBase visitor) => visitor.visitIE8Term(this); |
| 777 } |
| 778 |
| 779 class GroupTerm extends Expression { |
| 780 final List<LiteralTerm> _terms; |
| 781 |
| 782 GroupTerm(Span span) : _terms = [], super(span); |
| 783 |
| 784 add(LiteralTerm term) { |
| 785 _terms.add(term); |
| 786 } |
| 787 |
| 788 visit(VisitorBase visitor) => visitor.visitGroupTerm(this); |
| 789 } |
| 790 |
| 791 class ItemTerm extends NumberTerm { |
| 792 ItemTerm(var value, String t, Span span) : super(value, t, span); |
| 793 |
| 794 visit(VisitorBase visitor) => visitor.visitItemTerm(this); |
| 795 } |
| 796 |
| 797 class Expressions extends Expression { |
| 798 final List<Expression> expressions = []; |
| 799 |
| 800 Expressions(Span span): super(span); |
| 801 |
| 802 add(Expression expression) { |
| 803 expressions.add(expression); |
| 804 } |
| 805 |
| 806 visit(VisitorBase visitor) => visitor.visitExpressions(this); |
| 807 } |
| 808 |
| 809 class BinaryExpression extends Expression { |
| 810 final Token op; |
| 811 final Expression x; |
| 812 final Expression y; |
| 813 |
| 814 BinaryExpression(this.op, this.x, this.y, Span span): super(span); |
| 815 |
| 816 visit(VisitorBase visitor) => visitor.visitBinaryExpression(this); |
| 817 } |
| 818 |
| 819 class UnaryExpression extends Expression { |
| 820 final Token op; |
| 821 final Expression self; |
| 822 |
| 823 UnaryExpression(this.op, this.self, Span span): super(span); |
| 824 |
| 825 visit(VisitorBase visitor) => visitor.visitUnaryExpression(this); |
| 826 } |
| 827 |
| 828 abstract class DartStyleExpression extends TreeNode { |
| 829 static final int unknownType = 0; |
| 830 static final int fontStyle = 1; |
| 831 static final int marginStyle = 2; |
| 832 static final int borderStyle = 3; |
| 833 static final int paddingStyle = 4; |
| 834 static final int heightStyle = 5; |
| 835 static final int widthStyle = 6; |
| 836 |
| 837 final int _styleType; |
| 838 int priority; |
| 839 |
| 840 DartStyleExpression(this._styleType, Span span) : super(span); |
| 841 |
| 842 /* |
| 843 * Merges give 2 DartStyleExpression (or derived from DartStyleExpression, |
| 844 * e.g., FontExpression, etc.) will merge if the two expressions are of the |
| 845 * same property name (implies same exact type e.g, FontExpression). |
| 846 */ |
| 847 merged(DartStyleExpression newDartExpr); |
| 848 |
| 849 bool get isUnknown => _styleType == 0 || _styleType == null; |
| 850 bool get isFont => _styleType == fontStyle; |
| 851 bool get isMargin => _styleType == marginStyle; |
| 852 bool get isBorder => _styleType == borderStyle; |
| 853 bool get isPadding => _styleType == paddingStyle; |
| 854 bool get isHeight => _styleType == heightStyle; |
| 855 bool get isWidth => _styleType == widthStyle; |
| 856 bool get isBoxExpression => isMargin || isBorder || isPadding; |
| 857 |
| 858 bool isSame(DartStyleExpression other) => this._styleType == other._styleType; |
| 859 |
| 860 visit(VisitorBase visitor) => visitor.visitDartStyleExpression(this); |
| 861 } |
| 862 |
| 863 class FontExpression extends DartStyleExpression { |
| 864 Font font; |
| 865 |
| 866 // font-style font-variant font-weight font-size/line-height font-family |
| 867 FontExpression(Span span, {var size, List<String>family, |
| 868 int weight, String style, String variant, LineHeight lineHeight}) |
| 869 : super(DartStyleExpression.fontStyle, span) { |
| 870 // TODO(terry): Only px/pt for now need to handle all possible units to |
| 871 // support calc expressions on units. |
| 872 font = new Font(size : size is LengthTerm ? size.value : size, |
| 873 family: family, weight: weight, style: style, variant: variant, |
| 874 lineHeight: lineHeight); |
| 875 } |
| 876 |
| 877 merged(FontExpression newFontExpr) { |
| 878 if (this.isFont && newFontExpr.isFont) { |
| 879 return new FontExpression.merge(this, newFontExpr); |
| 880 } |
| 881 |
| 882 return null; |
| 883 } |
| 884 |
| 885 /** |
| 886 * Merge the two FontExpression and return the result. |
| 887 */ |
| 888 factory FontExpression.merge(FontExpression x, FontExpression y) { |
| 889 return new FontExpression._merge(x, y, y.span); |
| 890 } |
| 891 |
| 892 FontExpression._merge(FontExpression x, FontExpression y, Span span) |
| 893 : super(DartStyleExpression.fontStyle, span), |
| 894 font = new Font.merge(x.font, y.font); |
| 895 |
| 896 visit(VisitorBase visitor) => visitor.visitFontExpression(this); |
| 897 } |
| 898 |
| 899 abstract class BoxExpression extends DartStyleExpression { |
| 900 final BoxEdge box; |
| 901 |
| 902 BoxExpression(int styleType, Span span, this.box) |
| 903 : super(styleType, span); |
| 904 |
| 905 /* |
| 906 * Merges give 2 DartStyleExpression (or derived from DartStyleExpression, |
| 907 * e.g., FontExpression, etc.) will merge if the two expressions are of the |
| 908 * same property name (implies same exact type e.g, FontExpression). |
| 909 */ |
| 910 merged(BoxExpression newDartExpr); |
| 911 |
| 912 visit(VisitorBase visitor) => visitor.visitBoxExpression(this); |
| 913 |
| 914 String get formattedBoxEdge { |
| 915 if (box.top == box.left && box.top == box.bottom && |
| 916 box.top== box.right) { |
| 917 return '.uniform(${box.top})'; |
| 918 } else { |
| 919 var left = box.left == null ? 0 : box.left; |
| 920 var top = box.top == null ? 0 : box.top; |
| 921 var right = box.right == null ? 0 : box.right; |
| 922 var bottom = box.bottom == null ? 0 : box.bottom; |
| 923 return '.clockwiseFromTop($top,$right,$bottom,$left)'; |
| 924 } |
| 925 } |
| 926 } |
| 927 |
| 928 class MarginExpression extends BoxExpression { |
| 929 // TODO(terry): Does auto for margin need to be exposed to Dart UI framework? |
| 930 /** Margin expression ripped apart. */ |
| 931 MarginExpression(Span span, {num top, num right, num bottom, num left}) |
| 932 : super(DartStyleExpression.marginStyle, span, |
| 933 new BoxEdge(left, top, right, bottom)); |
| 934 |
| 935 MarginExpression.boxEdge(Span span, BoxEdge box) |
| 936 : super(DartStyleExpression.marginStyle, span, box); |
| 937 |
| 938 merged(MarginExpression newMarginExpr) { |
| 939 if (this.isMargin && newMarginExpr.isMargin) { |
| 940 return new MarginExpression.merge(this, newMarginExpr); |
| 941 } |
| 942 |
| 943 return null; |
| 944 } |
| 945 |
| 946 /** |
| 947 * Merge the two MarginExpressions and return the result. |
| 948 */ |
| 949 factory MarginExpression.merge(MarginExpression x, MarginExpression y) { |
| 950 return new MarginExpression._merge(x, y, y.span); |
| 951 } |
| 952 |
| 953 MarginExpression._merge(MarginExpression x, MarginExpression y, Span span) |
| 954 : super(x._styleType, span, new BoxEdge.merge(x.box, y.box)); |
| 955 |
| 956 visit(VisitorBase visitor) => visitor.visitMarginExpression(this); |
| 957 } |
| 958 |
| 959 class BorderExpression extends BoxExpression { |
| 960 /** Border expression ripped apart. */ |
| 961 BorderExpression(Span span, {num top, num right, num bottom, num left}) |
| 962 : super(DartStyleExpression.borderStyle, span, |
| 963 new BoxEdge(left, top, right, bottom)); |
| 964 |
| 965 BorderExpression.boxEdge(Span span, BoxEdge box) |
| 966 : super(DartStyleExpression.borderStyle, span, box); |
| 967 |
| 968 merged(BorderExpression newBorderExpr) { |
| 969 if (this.isBorder && newBorderExpr.isBorder) { |
| 970 return new BorderExpression.merge(this, newBorderExpr); |
| 971 } |
| 972 |
| 973 return null; |
| 974 } |
| 975 |
| 976 /** |
| 977 * Merge the two BorderExpression and return the result. |
| 978 */ |
| 979 factory BorderExpression.merge(BorderExpression x, BorderExpression y) { |
| 980 return new BorderExpression._merge(x, y, y.span); |
| 981 } |
| 982 |
| 983 BorderExpression._merge(BorderExpression x, BorderExpression y, |
| 984 Span span) |
| 985 : super(DartStyleExpression.borderStyle, span, |
| 986 new BoxEdge.merge(x.box, y.box)); |
| 987 |
| 988 visit(VisitorBase visitor) => visitor.visitBorderExpression(this); |
| 989 } |
| 990 |
| 991 class HeightExpression extends DartStyleExpression { |
| 992 final height; |
| 993 |
| 994 HeightExpression(Span span, this.height) |
| 995 : super(DartStyleExpression.heightStyle, span); |
| 996 |
| 997 merged(HeightExpression newHeightExpr) { |
| 998 if (this.isHeight && newHeightExpr.isHeight) { |
| 999 return newHeightExpr; |
| 1000 } |
| 1001 |
| 1002 return null; |
| 1003 } |
| 1004 |
| 1005 visit(VisitorBase visitor) => visitor.visitHeightExpression(this); |
| 1006 } |
| 1007 |
| 1008 class WidthExpression extends DartStyleExpression { |
| 1009 final width; |
| 1010 |
| 1011 WidthExpression(Span span, this.width) |
| 1012 : super(DartStyleExpression.widthStyle, span); |
| 1013 |
| 1014 merged(WidthExpression newWidthExpr) { |
| 1015 if (this.isWidth && newWidthExpr.isWidth) { |
| 1016 return newWidthExpr; |
| 1017 } |
| 1018 |
| 1019 return null; |
| 1020 } |
| 1021 |
| 1022 visit(VisitorBase visitor) => visitor.visitWidthExpression(this); |
| 1023 } |
| 1024 |
| 1025 class PaddingExpression extends BoxExpression { |
| 1026 /** Padding expression ripped apart. */ |
| 1027 PaddingExpression(Span span, {num top, num right, num bottom, num left}) |
| 1028 : super(DartStyleExpression.paddingStyle, span, |
| 1029 new BoxEdge(left, top, right, bottom)); |
| 1030 |
| 1031 PaddingExpression.boxEdge(Span span, BoxEdge box) |
| 1032 : super(DartStyleExpression.paddingStyle, span, box); |
| 1033 |
| 1034 merged(PaddingExpression newPaddingExpr) { |
| 1035 if (this.isPadding && newPaddingExpr.isPadding) { |
| 1036 return new PaddingExpression.merge(this, newPaddingExpr); |
| 1037 } |
| 1038 |
| 1039 return null; |
| 1040 } |
| 1041 |
| 1042 /** |
| 1043 * Merge the two PaddingExpression and return the result. |
| 1044 */ |
| 1045 factory PaddingExpression.merge(PaddingExpression x, PaddingExpression y) { |
| 1046 return new PaddingExpression._merge(x, y, y.span); |
| 1047 } |
| 1048 |
| 1049 PaddingExpression._merge(PaddingExpression x, PaddingExpression y, Span span) |
| 1050 : super(DartStyleExpression.paddingStyle, span, |
| 1051 new BoxEdge.merge(x.box, y.box)); |
| 1052 |
| 1053 visit(VisitorBase visitor) => visitor.visitPaddingExpression(this); |
| 1054 } |
OLD | NEW |