OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 | 3 |
4 /** | 4 /** |
5 * A simple recursive descent parser for CSS. | 5 * A simple recursive descent parser for CSS. |
6 */ | 6 */ |
7 class Parser { | 7 class Parser { |
8 Tokenizer tokenizer; | 8 Tokenizer tokenizer; |
9 | 9 |
10 var _fs; // If non-null filesystem to read files. | 10 var _fs; // If non-null filesystem to read files. |
(...skipping 19 matching lines...) Expand all Loading... |
30 // we encounter a } then stop we're inside of a template e.g., | 30 // we encounter a } then stop we're inside of a template e.g., |
31 // | 31 // |
32 // template ... { | 32 // template ... { |
33 // css { | 33 // css { |
34 // .item { | 34 // .item { |
35 // left: 10px; | 35 // left: 10px; |
36 // } | 36 // } |
37 // } | 37 // } |
38 // <div>...</div> | 38 // <div>...</div> |
39 // } | 39 // } |
40 // | 40 // |
41 Stylesheet parse([bool nestedCSS = false, var erroMsgRedirector = null]) { | 41 Stylesheet parse([bool nestedCSS = false, var erroMsgRedirector = null]) { |
42 // TODO(terry): Hack for migrating CSS errors back to template errors. | 42 // TODO(terry): Hack for migrating CSS errors back to template errors. |
43 _erroMsgRedirector = erroMsgRedirector; | 43 _erroMsgRedirector = erroMsgRedirector; |
44 | 44 |
45 List<ASTNode> productions = []; | 45 List<ASTNode> productions = []; |
46 | 46 |
47 int start = _peekToken.start; | 47 int start = _peekToken.start; |
48 while (!_maybeEat(TokenKind.END_OF_FILE) && | 48 while (!_maybeEat(TokenKind.END_OF_FILE) && |
49 (!nestedCSS && !_peekKind(TokenKind.RBRACE))) { | 49 (!nestedCSS && !_peekKind(TokenKind.RBRACE))) { |
50 // TODO(terry): Need to handle charset, import, media and page. | 50 // TODO(terry): Need to handle charset, import, media and page. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 SelectorGroup group = new SelectorGroup(selectors, _makeSpan(start)); | 192 SelectorGroup group = new SelectorGroup(selectors, _makeSpan(start)); |
193 | 193 |
194 _eat(TokenKind.RBRACE); | 194 _eat(TokenKind.RBRACE); |
195 | 195 |
196 return group; | 196 return group; |
197 } | 197 } |
198 | 198 |
199 /////////////////////////////////////////////////////////////////// | 199 /////////////////////////////////////////////////////////////////// |
200 // Productions | 200 // Productions |
201 /////////////////////////////////////////////////////////////////// | 201 /////////////////////////////////////////////////////////////////// |
202 | 202 |
203 processMedia([bool oneRequired = false]) { | 203 processMedia([bool oneRequired = false]) { |
204 List<String> media = []; | 204 List<String> media = []; |
205 | 205 |
206 while (_peekIdentifier()) { | 206 while (_peekIdentifier()) { |
207 // We have some media types. | 207 // We have some media types. |
208 var medium = identifier(); // Medium ident. | 208 var medium = identifier(); // Medium ident. |
209 media.add(medium); | 209 media.add(medium); |
210 if (!_maybeEat(TokenKind.COMMA)) { | 210 if (!_maybeEat(TokenKind.COMMA)) { |
211 // No more media types exit now. | 211 // No more media types exit now. |
212 break; | 212 break; |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 // | 649 // |
650 processDeclaration() { | 650 processDeclaration() { |
651 Declaration decl; | 651 Declaration decl; |
652 | 652 |
653 int start = _peekToken.start; | 653 int start = _peekToken.start; |
654 | 654 |
655 // IDENT ':' expr '!important'? | 655 // IDENT ':' expr '!important'? |
656 if (TokenKind.isIdentifier(_peekToken.kind)) { | 656 if (TokenKind.isIdentifier(_peekToken.kind)) { |
657 var propertyIdent = identifier(); | 657 var propertyIdent = identifier(); |
658 _eat(TokenKind.COLON); | 658 _eat(TokenKind.COLON); |
659 | 659 |
660 decl = new Declaration(propertyIdent, processExpr(), _makeSpan(start)); | 660 decl = new Declaration(propertyIdent, processExpr(), _makeSpan(start)); |
661 | 661 |
662 // Handle !important (prio) | 662 // Handle !important (prio) |
663 decl.important = _maybeEat(TokenKind.IMPORTANT); | 663 decl.important = _maybeEat(TokenKind.IMPORTANT); |
664 } | 664 } |
665 | 665 |
666 return decl; | 666 return decl; |
667 } | 667 } |
668 | 668 |
669 // Expression grammar: | 669 // Expression grammar: |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 | 756 |
757 try { | 757 try { |
758 int hexValue = parseHex(hexText); | 758 int hexValue = parseHex(hexText); |
759 return new HexColorTerm(hexValue, hexText, _makeSpan(start)); | 759 return new HexColorTerm(hexValue, hexText, _makeSpan(start)); |
760 } on HexNumberException catch (hne) { | 760 } on HexNumberException catch (hne) { |
761 _error('Bad hex number', _makeSpan(start)); | 761 _error('Bad hex number', _makeSpan(start)); |
762 } | 762 } |
763 break; | 763 break; |
764 case TokenKind.INTEGER: | 764 case TokenKind.INTEGER: |
765 t = _next(); | 765 t = _next(); |
766 value = Math.parseInt("${unary}${t.text}"); | 766 value = int.parse("${unary}${t.text}"); |
767 break; | 767 break; |
768 case TokenKind.DOUBLE: | 768 case TokenKind.DOUBLE: |
769 t = _next(); | 769 t = _next(); |
770 value = Math.parseDouble("${unary}${t.text}"); | 770 value = double.parse("${unary}${t.text}"); |
771 break; | 771 break; |
772 case TokenKind.SINGLE_QUOTE: | 772 case TokenKind.SINGLE_QUOTE: |
773 case TokenKind.DOUBLE_QUOTE: | 773 case TokenKind.DOUBLE_QUOTE: |
774 value = processQuotedString(false); | 774 value = processQuotedString(false); |
775 value = '"${value}"'; | 775 value = '"${value}"'; |
776 return new LiteralTerm(value, value, _makeSpan(start)); | 776 return new LiteralTerm(value, value, _makeSpan(start)); |
777 case TokenKind.LPAREN: | 777 case TokenKind.LPAREN: |
778 _next(); | 778 _next(); |
779 | 779 |
780 GroupTerm group = new GroupTerm(_makeSpan(start)); | 780 GroupTerm group = new GroupTerm(_makeSpan(start)); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 } | 971 } |
972 | 972 |
973 return null; | 973 return null; |
974 } | 974 } |
975 | 975 |
976 identifier() { | 976 identifier() { |
977 var tok = _next(); | 977 var tok = _next(); |
978 if (!TokenKind.isIdentifier(tok.kind)) { | 978 if (!TokenKind.isIdentifier(tok.kind)) { |
979 _error('expected identifier, but found $tok', tok.span); | 979 _error('expected identifier, but found $tok', tok.span); |
980 } | 980 } |
981 | 981 |
982 return new Identifier(tok.text, _makeSpan(tok.start)); | 982 return new Identifier(tok.text, _makeSpan(tok.start)); |
983 } | 983 } |
984 | 984 |
985 // TODO(terry): Move this to base <= 36 and into shared code. | 985 // TODO(terry): Move this to base <= 36 and into shared code. |
986 static int _hexDigit(int c) { | 986 static int _hexDigit(int c) { |
987 if(c >= 48/*0*/ && c <= 57/*9*/) { | 987 if(c >= 48/*0*/ && c <= 57/*9*/) { |
988 return c - 48; | 988 return c - 48; |
989 } else if (c >= 97/*a*/ && c <= 102/*f*/) { | 989 } else if (c >= 97/*a*/ && c <= 102/*f*/) { |
990 return c - 87; | 990 return c - 87; |
991 } else if (c >= 65/*A*/ && c <= 70/*F*/) { | 991 } else if (c >= 65/*A*/ && c <= 70/*F*/) { |
(...skipping 16 matching lines...) Expand all Loading... |
1008 | 1008 |
1009 return result; | 1009 return result; |
1010 } | 1010 } |
1011 } | 1011 } |
1012 | 1012 |
1013 /** Not a hex number. */ | 1013 /** Not a hex number. */ |
1014 class HexNumberException implements Exception { | 1014 class HexNumberException implements Exception { |
1015 HexNumberException(); | 1015 HexNumberException(); |
1016 } | 1016 } |
1017 | 1017 |
OLD | NEW |