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_maps/span.dart' show SourceFile, Span, FileSpan; | 9 import 'package:source_span/source_span.dart'; |
10 | 10 |
11 import "visitor.dart"; | 11 import "visitor.dart"; |
12 import 'src/messages.dart'; | 12 import 'src/messages.dart'; |
13 import 'src/options.dart'; | 13 import 'src/options.dart'; |
14 | 14 |
15 part 'src/analyzer.dart'; | 15 part 'src/analyzer.dart'; |
16 part 'src/polyfill.dart'; | 16 part 'src/polyfill.dart'; |
17 part 'src/property.dart'; | 17 part 'src/property.dart'; |
18 part 'src/token.dart'; | 18 part 'src/token.dart'; |
19 part 'src/tokenizer_base.dart'; | 19 part 'src/tokenizer_base.dart'; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 List<StyleSheet> includes: null}) { | 52 List<StyleSheet> includes: null}) { |
53 | 53 |
54 if (includes == null) { | 54 if (includes == null) { |
55 includes = []; | 55 includes = []; |
56 } | 56 } |
57 | 57 |
58 var source = _inputAsString(input); | 58 var source = _inputAsString(input); |
59 | 59 |
60 _createMessages(errors: errors, options: options); | 60 _createMessages(errors: errors, options: options); |
61 | 61 |
62 var file = new SourceFile.text(null, source); | 62 var file = new SourceFile(source); |
63 | 63 |
64 var tree = new _Parser(file, source).parse(); | 64 var tree = new _Parser(file, source).parse(); |
65 | 65 |
66 analyze([tree], errors: errors, options: options); | 66 analyze([tree], errors: errors, options: options); |
67 | 67 |
68 if (polyfill) { | 68 if (polyfill) { |
69 var processCss = new PolyFill(messages, true); | 69 var processCss = new PolyFill(messages, true); |
70 processCss.process(tree, includes: includes); | 70 processCss.process(tree, includes: includes); |
71 } | 71 } |
72 | 72 |
(...skipping 11 matching lines...) Expand all Loading... |
84 /** | 84 /** |
85 * Parse the [input] CSS stylesheet into a tree. The [input] can be a [String], | 85 * Parse the [input] CSS stylesheet into a tree. The [input] can be a [String], |
86 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional | 86 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional |
87 * [errors] list will contain each error/warning as a [Message]. | 87 * [errors] list will contain each error/warning as a [Message]. |
88 */ | 88 */ |
89 StyleSheet parse(input, {List<Message> errors, List<String> options}) { | 89 StyleSheet parse(input, {List<Message> errors, List<String> options}) { |
90 var source = _inputAsString(input); | 90 var source = _inputAsString(input); |
91 | 91 |
92 _createMessages(errors: errors, options: options); | 92 _createMessages(errors: errors, options: options); |
93 | 93 |
94 var file = new SourceFile.text(null, source); | 94 var file = new SourceFile(source); |
95 return new _Parser(file, source).parse(); | 95 return new _Parser(file, source).parse(); |
96 } | 96 } |
97 | 97 |
98 /** | 98 /** |
99 * Parse the [input] CSS selector into a tree. The [input] can be a [String], | 99 * Parse the [input] CSS selector into a tree. The [input] can be a [String], |
100 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional | 100 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional |
101 * [errors] list will contain each error/warning as a [Message]. | 101 * [errors] list will contain each error/warning as a [Message]. |
102 */ | 102 */ |
103 // TODO(jmesserly): should rename "parseSelector" and return Selector | 103 // TODO(jmesserly): should rename "parseSelector" and return Selector |
104 StyleSheet selector(input, {List<Message> errors}) { | 104 StyleSheet selector(input, {List<Message> errors}) { |
105 var source = _inputAsString(input); | 105 var source = _inputAsString(input); |
106 | 106 |
107 _createMessages(errors: errors); | 107 _createMessages(errors: errors); |
108 | 108 |
109 var file = new SourceFile.text(null, source); | 109 var file = new SourceFile(source); |
110 return (new _Parser(file, source) | 110 return (new _Parser(file, source) |
111 ..tokenizer.inSelector = true) | 111 ..tokenizer.inSelector = true) |
112 .parseSelector(); | 112 .parseSelector(); |
113 } | 113 } |
114 | 114 |
115 SelectorGroup parseSelectorGroup(input, {List<Message> errors}) { | 115 SelectorGroup parseSelectorGroup(input, {List<Message> errors}) { |
116 var source = _inputAsString(input); | 116 var source = _inputAsString(input); |
117 | 117 |
118 _createMessages(errors: errors); | 118 _createMessages(errors: errors); |
119 | 119 |
120 var file = new SourceFile.text(null, source); | 120 var file = new SourceFile(source); |
121 return (new _Parser(file, source) | 121 return (new _Parser(file, source) |
122 // TODO(jmesserly): this fix should be applied to the parser. It's tricky | 122 // TODO(jmesserly): this fix should be applied to the parser. It's tricky |
123 // because by the time the flag is set one token has already been fetched. | 123 // because by the time the flag is set one token has already been fetched. |
124 ..tokenizer.inSelector = true) | 124 ..tokenizer.inSelector = true) |
125 .processSelectorGroup(); | 125 .processSelectorGroup(); |
126 } | 126 } |
127 | 127 |
128 String _inputAsString(input) { | 128 String _inputAsString(input) { |
129 String source; | 129 String source; |
130 | 130 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 var tok = _next(); | 313 var tok = _next(); |
314 var message; | 314 var message; |
315 try { | 315 try { |
316 message = 'expected $expected, but found $tok'; | 316 message = 'expected $expected, but found $tok'; |
317 } catch (e) { | 317 } catch (e) { |
318 message = 'parsing error expected $expected'; | 318 message = 'parsing error expected $expected'; |
319 } | 319 } |
320 _error(message, tok.span); | 320 _error(message, tok.span); |
321 } | 321 } |
322 | 322 |
323 void _error(String message, Span location) { | 323 void _error(String message, SourceSpan location) { |
324 if (location == null) { | 324 if (location == null) { |
325 location = _peekToken.span; | 325 location = _peekToken.span; |
326 } | 326 } |
327 messages.error(message, location); | 327 messages.error(message, location); |
328 } | 328 } |
329 | 329 |
330 void _warning(String message, Span location) { | 330 void _warning(String message, SourceSpan location) { |
331 if (location == null) { | 331 if (location == null) { |
332 location = _peekToken.span; | 332 location = _peekToken.span; |
333 } | 333 } |
334 messages.warning(message, location); | 334 messages.warning(message, location); |
335 } | 335 } |
336 | 336 |
337 Span _makeSpan(int start) { | 337 SourceSpan _makeSpan(int start) { |
338 // TODO(terry): there are places where we are creating spans before we eat | 338 // TODO(terry): there are places where we are creating spans before we eat |
339 // the tokens, so using _previousToken.end is not always valid. | 339 // the tokens, so using _previousToken.end is not always valid. |
340 var end = _previousToken != null && _previousToken.end >= start | 340 var end = _previousToken != null && _previousToken.end >= start |
341 ? _previousToken.end : _peekToken.end; | 341 ? _previousToken.end : _peekToken.end; |
342 return file.span(start, end); | 342 return file.span(start, end); |
343 } | 343 } |
344 | 344 |
345 /////////////////////////////////////////////////////////////////// | 345 /////////////////////////////////////////////////////////////////// |
346 // Top level productions | 346 // Top level productions |
347 /////////////////////////////////////////////////////////////////// | 347 /////////////////////////////////////////////////////////////////// |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 if (_maybeEat(TokenKind.COLON)) { | 935 if (_maybeEat(TokenKind.COLON)) { |
936 exprs = processExpr(); | 936 exprs = processExpr(); |
937 } | 937 } |
938 | 938 |
939 return new VarDefinition(definedName, exprs, _makeSpan(start)); | 939 return new VarDefinition(definedName, exprs, _makeSpan(start)); |
940 } | 940 } |
941 | 941 |
942 return tokId; | 942 return tokId; |
943 } | 943 } |
944 | 944 |
945 IncludeDirective processInclude(Span span, {bool eatSemiColon: true}) { | 945 IncludeDirective processInclude(SourceSpan span, {bool eatSemiColon: true}) { |
946 /* Stylet grammar: | 946 /* Stylet grammar: |
947 * | 947 * |
948 * @include IDENT [(args,...)]; | 948 * @include IDENT [(args,...)]; |
949 */ | 949 */ |
950 _next(); | 950 _next(); |
951 | 951 |
952 var name; | 952 var name; |
953 if (_peekIdentifier()) { | 953 if (_peekIdentifier()) { |
954 name = identifier(); | 954 name = identifier(); |
955 } | 955 } |
(...skipping 1320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2276 expr.expressions[0] = varUsage; | 2276 expr.expressions[0] = varUsage; |
2277 return expr.expressions; | 2277 return expr.expressions; |
2278 } | 2278 } |
2279 break; | 2279 break; |
2280 } | 2280 } |
2281 | 2281 |
2282 return processDimension(t, value, _makeSpan(start)); | 2282 return processDimension(t, value, _makeSpan(start)); |
2283 } | 2283 } |
2284 | 2284 |
2285 /** Process all dimension units. */ | 2285 /** Process all dimension units. */ |
2286 LiteralTerm processDimension(Token t, var value, Span span) { | 2286 LiteralTerm processDimension(Token t, var value, SourceSpan span) { |
2287 LiteralTerm term; | 2287 LiteralTerm term; |
2288 var unitType = this._peek(); | 2288 var unitType = this._peek(); |
2289 | 2289 |
2290 switch (unitType) { | 2290 switch (unitType) { |
2291 case TokenKind.UNIT_EM: | 2291 case TokenKind.UNIT_EM: |
2292 term = new EmTerm(value, t.text, span); | 2292 term = new EmTerm(value, t.text, span); |
2293 _next(); // Skip the unit | 2293 _next(); // Skip the unit |
2294 break; | 2294 break; |
2295 case TokenKind.UNIT_EX: | 2295 case TokenKind.UNIT_EX: |
2296 term = new ExTerm(value, t.text, span); | 2296 term = new ExTerm(value, t.text, span); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2531 return c - 48; | 2531 return c - 48; |
2532 } else if (c >= 97/*a*/ && c <= 102/*f*/) { | 2532 } else if (c >= 97/*a*/ && c <= 102/*f*/) { |
2533 return c - 87; | 2533 return c - 87; |
2534 } else if (c >= 65/*A*/ && c <= 70/*F*/) { | 2534 } else if (c >= 65/*A*/ && c <= 70/*F*/) { |
2535 return c - 55; | 2535 return c - 55; |
2536 } else { | 2536 } else { |
2537 return -1; | 2537 return -1; |
2538 } | 2538 } |
2539 } | 2539 } |
2540 | 2540 |
2541 HexColorTerm _parseHex(String hexText, Span span) { | 2541 HexColorTerm _parseHex(String hexText, SourceSpan span) { |
2542 var hexValue = 0; | 2542 var hexValue = 0; |
2543 | 2543 |
2544 for (var i = 0; i < hexText.length; i++) { | 2544 for (var i = 0; i < hexText.length; i++) { |
2545 var digit = _hexDigit(hexText.codeUnitAt(i)); | 2545 var digit = _hexDigit(hexText.codeUnitAt(i)); |
2546 if (digit < 0) { | 2546 if (digit < 0) { |
2547 _warning('Bad hex number', span); | 2547 _warning('Bad hex number', span); |
2548 return new HexColorTerm(new BAD_HEX_VALUE(), hexText, span); | 2548 return new HexColorTerm(new BAD_HEX_VALUE(), hexText, span); |
2549 } | 2549 } |
2550 hexValue = (hexValue << 4) + digit; | 2550 hexValue = (hexValue << 4) + digit; |
2551 } | 2551 } |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2695 | 2695 |
2696 if (replace != null && result == null) { | 2696 if (replace != null && result == null) { |
2697 result = new StringBuffer(text.substring(0, i)); | 2697 result = new StringBuffer(text.substring(0, i)); |
2698 } | 2698 } |
2699 | 2699 |
2700 if (result != null) result.write(replace != null ? replace : text[i]); | 2700 if (result != null) result.write(replace != null ? replace : text[i]); |
2701 } | 2701 } |
2702 | 2702 |
2703 return result == null ? text : result.toString(); | 2703 return result == null ? text : result.toString(); |
2704 } | 2704 } |
OLD | NEW |