| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library csslib.parser; | 5 library csslib.parser; |
| 6 | 6 |
| 7 import 'dart:math' as math; | 7 import 'dart:math' as math; |
| 8 | 8 |
| 9 import 'package:source_span/source_span.dart'; | 9 import 'package:source_span/source_span.dart'; |
| 10 | 10 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 _peekToken = tokenizer.next(); | 204 _peekToken = tokenizer.next(); |
| 205 } | 205 } |
| 206 | 206 |
| 207 /** Main entry point for parsing an entire CSS file. */ | 207 /** Main entry point for parsing an entire CSS file. */ |
| 208 StyleSheet parse() { | 208 StyleSheet parse() { |
| 209 List<TreeNode> productions = []; | 209 List<TreeNode> productions = []; |
| 210 | 210 |
| 211 var start = _peekToken.span; | 211 var start = _peekToken.span; |
| 212 while (!_maybeEat(TokenKind.END_OF_FILE) && !_peekKind(TokenKind.RBRACE)) { | 212 while (!_maybeEat(TokenKind.END_OF_FILE) && !_peekKind(TokenKind.RBRACE)) { |
| 213 // TODO(terry): Need to handle charset. | 213 // TODO(terry): Need to handle charset. |
| 214 var directive = processDirective(); | 214 final rule = processRule(); |
| 215 if (directive != null) { | 215 if (rule != null) { |
| 216 productions.add(directive); | 216 productions.add(rule); |
| 217 _maybeEat(TokenKind.SEMICOLON); | |
| 218 } else { | 217 } else { |
| 219 RuleSet ruleset = processRuleSet(); | 218 break; |
| 220 if (ruleset != null) { | |
| 221 productions.add(ruleset); | |
| 222 } else { | |
| 223 break; | |
| 224 } | |
| 225 } | 219 } |
| 226 } | 220 } |
| 227 | 221 |
| 228 checkEndOfFile(); | 222 checkEndOfFile(); |
| 229 | 223 |
| 230 return new StyleSheet(productions, _makeSpan(start)); | 224 return new StyleSheet(productions, _makeSpan(start)); |
| 231 } | 225 } |
| 232 | 226 |
| 233 /** Main entry point for parsing a simple selector sequence. */ | 227 /** Main entry point for parsing a simple selector sequence. */ |
| 234 StyleSheet parseSelector() { | 228 StyleSheet parseSelector() { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 } | 510 } |
| 517 | 511 |
| 518 return new ImportDirective(importStr.trim(), medias, _makeSpan(start)); | 512 return new ImportDirective(importStr.trim(), medias, _makeSpan(start)); |
| 519 | 513 |
| 520 case TokenKind.DIRECTIVE_MEDIA: | 514 case TokenKind.DIRECTIVE_MEDIA: |
| 521 _next(); | 515 _next(); |
| 522 | 516 |
| 523 // Any medias? | 517 // Any medias? |
| 524 var media = processMediaQueryList(); | 518 var media = processMediaQueryList(); |
| 525 | 519 |
| 526 List<TreeNode> rulesets = []; | 520 List<TreeNode> rules = []; |
| 527 if (_maybeEat(TokenKind.LBRACE)) { | 521 if (_maybeEat(TokenKind.LBRACE)) { |
| 528 while (!_maybeEat(TokenKind.END_OF_FILE)) { | 522 while (!_maybeEat(TokenKind.END_OF_FILE)) { |
| 529 RuleSet ruleset = processRuleSet(); | 523 final rule = processRule(); |
| 530 if (ruleset == null) break; | 524 if (rule == null) break; |
| 531 rulesets.add(ruleset); | 525 rules.add(rule); |
| 532 } | 526 } |
| 533 | 527 |
| 534 if (!_maybeEat(TokenKind.RBRACE)) { | 528 if (!_maybeEat(TokenKind.RBRACE)) { |
| 535 _error('expected } after ruleset for @media', _peekToken.span); | 529 _error('expected } after ruleset for @media', _peekToken.span); |
| 536 } | 530 } |
| 537 } else { | 531 } else { |
| 538 _error('expected { after media before ruleset', _peekToken.span); | 532 _error('expected { after media before ruleset', _peekToken.span); |
| 539 } | 533 } |
| 540 return new MediaDirective(media, rulesets, _makeSpan(start)); | 534 return new MediaDirective(media, rules, _makeSpan(start)); |
| 541 | 535 |
| 542 case TokenKind.DIRECTIVE_HOST: | 536 case TokenKind.DIRECTIVE_HOST: |
| 543 _next(); | 537 _next(); |
| 544 | 538 |
| 545 List<TreeNode> rulesets = []; | 539 List<TreeNode> rules = []; |
| 546 if (_maybeEat(TokenKind.LBRACE)) { | 540 if (_maybeEat(TokenKind.LBRACE)) { |
| 547 while (!_maybeEat(TokenKind.END_OF_FILE)) { | 541 while (!_maybeEat(TokenKind.END_OF_FILE)) { |
| 548 RuleSet ruleset = processRuleSet(); | 542 final rule = processRule(); |
| 549 if (ruleset == null) break; | 543 if (rule == null) break; |
| 550 rulesets.add(ruleset); | 544 rules.add(rule); |
| 551 } | 545 } |
| 552 | 546 |
| 553 if (!_maybeEat(TokenKind.RBRACE)) { | 547 if (!_maybeEat(TokenKind.RBRACE)) { |
| 554 _error('expected } after ruleset for @host', _peekToken.span); | 548 _error('expected } after ruleset for @host', _peekToken.span); |
| 555 } | 549 } |
| 556 } else { | 550 } else { |
| 557 _error('expected { after host before ruleset', _peekToken.span); | 551 _error('expected { after host before ruleset', _peekToken.span); |
| 558 } | 552 } |
| 559 return new HostDirective(rulesets, _makeSpan(start)); | 553 return new HostDirective(rules, _makeSpan(start)); |
| 560 | 554 |
| 561 case TokenKind.DIRECTIVE_PAGE: | 555 case TokenKind.DIRECTIVE_PAGE: |
| 562 /* | 556 /* |
| 563 * @page S* IDENT? pseudo_page? | 557 * @page S* IDENT? pseudo_page? |
| 564 * S* '{' S* | 558 * S* '{' S* |
| 565 * [ declaration | margin ]? | 559 * [ declaration | margin ]? |
| 566 * [ ';' S* [ declaration | margin ]? ]* '}' S* | 560 * [ ';' S* [ declaration | margin ]? ]* '}' S* |
| 567 * | 561 * |
| 568 * pseudo_page : | 562 * pseudo_page : |
| 569 * ':' [ "left" | "right" | "first" ] | 563 * ':' [ "left" | "right" | "first" ] |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 if (_peekIdentifier()) { | 695 if (_peekIdentifier()) { |
| 702 name = identifier(); | 696 name = identifier(); |
| 703 } | 697 } |
| 704 | 698 |
| 705 _eat(TokenKind.LBRACE); | 699 _eat(TokenKind.LBRACE); |
| 706 | 700 |
| 707 List<TreeNode> productions = []; | 701 List<TreeNode> productions = []; |
| 708 | 702 |
| 709 start = _peekToken.span; | 703 start = _peekToken.span; |
| 710 while (!_maybeEat(TokenKind.END_OF_FILE)) { | 704 while (!_maybeEat(TokenKind.END_OF_FILE)) { |
| 711 RuleSet ruleset = processRuleSet(); | 705 final rule = processRule(); |
| 712 if (ruleset == null) { | 706 if (rule == null) { |
| 713 break; | 707 break; |
| 714 } | 708 } |
| 715 productions.add(ruleset); | 709 productions.add(rule); |
| 716 } | 710 } |
| 717 | 711 |
| 718 _eat(TokenKind.RBRACE); | 712 _eat(TokenKind.RBRACE); |
| 719 | 713 |
| 720 return new StyletDirective(name, productions, _makeSpan(start)); | 714 return new StyletDirective(name, productions, _makeSpan(start)); |
| 721 | 715 |
| 722 case TokenKind.DIRECTIVE_NAMESPACE: | 716 case TokenKind.DIRECTIVE_NAMESPACE: |
| 723 /* Namespace grammar: | 717 /* Namespace grammar: |
| 724 * | 718 * |
| 725 * @namespace S* [namespace_prefix S*]? [STRING|URI] S* ';' S* | 719 * @namespace S* [namespace_prefix S*]? [STRING|URI] S* ';' S* |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 return new SupportsConditionInParens(declaration, _makeSpan(start)); | 1108 return new SupportsConditionInParens(declaration, _makeSpan(start)); |
| 1115 } | 1109 } |
| 1116 | 1110 |
| 1117 ViewportDirective processViewportDirective() { | 1111 ViewportDirective processViewportDirective() { |
| 1118 var start = _peekToken.span; | 1112 var start = _peekToken.span; |
| 1119 var name = _next().text; | 1113 var name = _next().text; |
| 1120 var declarations = processDeclarations(); | 1114 var declarations = processDeclarations(); |
| 1121 return new ViewportDirective(name, declarations, _makeSpan(start)); | 1115 return new ViewportDirective(name, declarations, _makeSpan(start)); |
| 1122 } | 1116 } |
| 1123 | 1117 |
| 1124 RuleSet processRuleSet([SelectorGroup selectorGroup]) { | 1118 TreeNode processRule([SelectorGroup selectorGroup]) { |
| 1125 if (selectorGroup == null) { | 1119 if (selectorGroup == null) { |
| 1120 final directive = processDirective(); |
| 1121 if (directive != null) { |
| 1122 _maybeEat(TokenKind.SEMICOLON); |
| 1123 return directive; |
| 1124 } |
| 1126 selectorGroup = processSelectorGroup(); | 1125 selectorGroup = processSelectorGroup(); |
| 1127 } | 1126 } |
| 1128 if (selectorGroup != null) { | 1127 if (selectorGroup != null) { |
| 1129 return new RuleSet( | 1128 return new RuleSet( |
| 1130 selectorGroup, processDeclarations(), selectorGroup.span); | 1129 selectorGroup, processDeclarations(), selectorGroup.span); |
| 1131 } | 1130 } |
| 1132 return null; | 1131 return null; |
| 1133 } | 1132 } |
| 1134 | 1133 |
| 1135 List<TreeNode> processGroupRuleBody() { | 1134 List<TreeNode> processGroupRuleBody() { |
| 1136 var nodes = <TreeNode>[]; | 1135 var nodes = <TreeNode>[]; |
| 1137 while (!(_peekKind(TokenKind.RBRACE) || _peekKind(TokenKind.END_OF_FILE))) { | 1136 while (!(_peekKind(TokenKind.RBRACE) || _peekKind(TokenKind.END_OF_FILE))) { |
| 1138 var directive = processDirective(); | 1137 var rule = processRule(); |
| 1139 if (directive != null) { | 1138 if (rule != null) { |
| 1140 nodes.add(directive); | 1139 nodes.add(rule); |
| 1141 continue; | |
| 1142 } | |
| 1143 var ruleSet = processRuleSet(); | |
| 1144 if (ruleSet != null) { | |
| 1145 nodes.add(ruleSet); | |
| 1146 continue; | 1140 continue; |
| 1147 } | 1141 } |
| 1148 break; | 1142 break; |
| 1149 } | 1143 } |
| 1150 return nodes; | 1144 return nodes; |
| 1151 } | 1145 } |
| 1152 | 1146 |
| 1153 /** | 1147 /** |
| 1154 * Look ahead to see if what should be a declaration is really a selector. | 1148 * Look ahead to see if what should be a declaration is really a selector. |
| 1155 * If it's a selector than it's a nested selector. This support's Less' | 1149 * If it's a selector than it's a nested selector. This support's Less' |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 | 1198 |
| 1205 if (checkBrace) _eat(TokenKind.LBRACE); | 1199 if (checkBrace) _eat(TokenKind.LBRACE); |
| 1206 | 1200 |
| 1207 var decls = <TreeNode>[]; | 1201 var decls = <TreeNode>[]; |
| 1208 var dartStyles = []; // List of latest styles exposed to Dart. | 1202 var dartStyles = []; // List of latest styles exposed to Dart. |
| 1209 | 1203 |
| 1210 do { | 1204 do { |
| 1211 var selectorGroup = _nestedSelector(); | 1205 var selectorGroup = _nestedSelector(); |
| 1212 while (selectorGroup != null) { | 1206 while (selectorGroup != null) { |
| 1213 // Nested selector so process as a ruleset. | 1207 // Nested selector so process as a ruleset. |
| 1214 var ruleset = processRuleSet(selectorGroup); | 1208 var ruleset = processRule(selectorGroup); |
| 1215 decls.add(ruleset); | 1209 decls.add(ruleset); |
| 1216 selectorGroup = _nestedSelector(); | 1210 selectorGroup = _nestedSelector(); |
| 1217 } | 1211 } |
| 1218 | 1212 |
| 1219 Declaration decl = processDeclaration(dartStyles); | 1213 Declaration decl = processDeclaration(dartStyles); |
| 1220 if (decl != null) { | 1214 if (decl != null) { |
| 1221 if (decl.hasDartStyle) { | 1215 if (decl.hasDartStyle) { |
| 1222 var newDartStyle = decl.dartStyle; | 1216 var newDartStyle = decl.dartStyle; |
| 1223 | 1217 |
| 1224 // Replace or add latest Dart style. | 1218 // Replace or add latest Dart style. |
| (...skipping 1724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2949 | 2943 |
| 2950 if (replace != null && result == null) { | 2944 if (replace != null && result == null) { |
| 2951 result = new StringBuffer(text.substring(0, i)); | 2945 result = new StringBuffer(text.substring(0, i)); |
| 2952 } | 2946 } |
| 2953 | 2947 |
| 2954 if (result != null) result.write(replace != null ? replace : text[i]); | 2948 if (result != null) result.write(replace != null ? replace : text[i]); |
| 2955 } | 2949 } |
| 2956 | 2950 |
| 2957 return result == null ? text : result.toString(); | 2951 return result == null ? text : result.toString(); |
| 2958 } | 2952 } |
| OLD | NEW |