Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: packages/csslib/lib/parser.dart

Issue 1521693002: Roll Observatory deps (charted -> ^0.3.0) (Closed) Base URL: https://chromium.googlesource.com/external/github.com/dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « packages/csslib/README.md ('k') | packages/csslib/lib/src/analyzer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 57
58 _createMessages(errors: errors, options: options); 58 _createMessages(errors: errors, options: options);
59 59
60 var file = new SourceFile(source); 60 var file = new SourceFile(source);
61 61
62 var tree = new _Parser(file, source).parse(); 62 var tree = new _Parser(file, source).parse();
63 63
64 analyze([tree], errors: errors, options: options); 64 analyze([tree], errors: errors, options: options);
65 65
66 if (polyfill) { 66 if (polyfill) {
67 var processCss = new PolyFill(messages, true); 67 var processCss = new PolyFill(messages);
68 processCss.process(tree, includes: includes); 68 processCss.process(tree, includes: includes);
69 } 69 }
70 70
71 return tree; 71 return tree;
72 } 72 }
73 73
74 /** Analyze the CSS file. */ 74 /** Analyze the CSS file. */
75 void analyze(List<StyleSheet> styleSheets, 75 void analyze(List<StyleSheet> styleSheets,
76 {List<Message> errors, PreprocessorOptions options}) { 76 {List<Message> errors, PreprocessorOptions options}) {
77 _createMessages(errors: errors, options: options); 77 _createMessages(errors: errors, options: options);
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 andOp = TokenKind.matchMediaOperator(op, 0, opLen) == 423 andOp = TokenKind.matchMediaOperator(op, 0, opLen) ==
424 TokenKind.MEDIA_OP_AND; 424 TokenKind.MEDIA_OP_AND;
425 if (!andOp) break; 425 if (!andOp) break;
426 _next(); 426 _next();
427 } 427 }
428 } 428 }
429 429
430 if (unaryOp != -1 || type != null || exprs.length > 0) { 430 if (unaryOp != -1 || type != null || exprs.length > 0) {
431 return new MediaQuery(unaryOp, type, exprs, _makeSpan(start)); 431 return new MediaQuery(unaryOp, type, exprs, _makeSpan(start));
432 } 432 }
433 return null;
433 } 434 }
434 435
435 MediaExpression processMediaExpression([bool andOperator = false]) { 436 MediaExpression processMediaExpression([bool andOperator = false]) {
436 var start = _peekToken.span; 437 var start = _peekToken.span;
437 438
438 // Grammar: '(' S* media_feature S* [ ':' S* expr ]? ')' S* 439 // Grammar: '(' S* media_feature S* [ ':' S* expr ]? ')' S*
439 if (_maybeEat(TokenKind.LPAREN)) { 440 if (_maybeEat(TokenKind.LPAREN)) {
440 if (_peekIdentifier()) { 441 if (_peekIdentifier()) {
441 var feature = identifier(); // Media feature. 442 var feature = identifier(); // Media feature.
442 while (_maybeEat(TokenKind.COLON)) { 443 while (_maybeEat(TokenKind.COLON)) {
443 var startExpr = _peekToken.span; 444 var startExpr = _peekToken.span;
444 var exprs = processExpr(); 445 var exprs = processExpr();
445 if (_maybeEat(TokenKind.RPAREN)) { 446 if (_maybeEat(TokenKind.RPAREN)) {
446 return new MediaExpression( 447 return new MediaExpression(
447 andOperator, feature, exprs, _makeSpan(startExpr)); 448 andOperator, feature, exprs, _makeSpan(startExpr));
448 } else if (isChecked) { 449 } else if (isChecked) {
449 _warning("Missing parenthesis around media expression", 450 _warning("Missing parenthesis around media expression",
450 _makeSpan(start)); 451 _makeSpan(start));
451 return null; 452 return null;
452 } 453 }
453 } 454 }
454 } else if (isChecked) { 455 } else if (isChecked) {
455 _warning("Missing media feature in media expression", _makeSpan(start)); 456 _warning("Missing media feature in media expression", _makeSpan(start));
456 return null;
457 } 457 }
458 } 458 }
459 return null;
459 } 460 }
460 461
461 /** 462 /**
462 * Directive grammar: 463 * Directive grammar:
463 * 464 *
464 * import: '@import' [string | URI] media_list? 465 * import: '@import' [string | URI] media_list?
465 * media: '@media' media_query_list '{' ruleset '}' 466 * media: '@media' media_query_list '{' ruleset '}'
466 * page: '@page' [':' IDENT]? '{' declarations '}' 467 * page: '@page' [':' IDENT]? '{' declarations '}'
467 * stylet: '@stylet' IDENT '{' ruleset '}' 468 * stylet: '@stylet' IDENT '{' ruleset '}'
468 * media_query_list: IDENT [',' IDENT] 469 * media_query_list: IDENT [',' IDENT]
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 mustHaveParam = true; 792 mustHaveParam = true;
792 continue; 793 continue;
793 } 794 }
794 keepGoing = !_maybeEat(TokenKind.RPAREN); 795 keepGoing = !_maybeEat(TokenKind.RPAREN);
795 } 796 }
796 } 797 }
797 798
798 _eat(TokenKind.LBRACE); 799 _eat(TokenKind.LBRACE);
799 800
800 List<TreeNode> productions = []; 801 List<TreeNode> productions = [];
801 List<TreeNode> declarations = [];
802 var mixinDirective; 802 var mixinDirective;
803 803
804 var start = _peekToken.span; 804 var start = _peekToken.span;
805 while (!_maybeEat(TokenKind.END_OF_FILE)) { 805 while (!_maybeEat(TokenKind.END_OF_FILE)) {
806 var directive = processDirective(); 806 var directive = processDirective();
807 if (directive != null) { 807 if (directive != null) {
808 productions.add(directive); 808 productions.add(directive);
809 continue; 809 continue;
810 } 810 }
811 811
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 } 977 }
978 978
979 RuleSet processRuleSet([SelectorGroup selectorGroup]) { 979 RuleSet processRuleSet([SelectorGroup selectorGroup]) {
980 if (selectorGroup == null) { 980 if (selectorGroup == null) {
981 selectorGroup = processSelectorGroup(); 981 selectorGroup = processSelectorGroup();
982 } 982 }
983 if (selectorGroup != null) { 983 if (selectorGroup != null) {
984 return new RuleSet( 984 return new RuleSet(
985 selectorGroup, processDeclarations(), selectorGroup.span); 985 selectorGroup, processDeclarations(), selectorGroup.span);
986 } 986 }
987 return null;
987 } 988 }
988 989
989 /** 990 /**
990 * Look ahead to see if what should be a declaration is really a selector. 991 * Look ahead to see if what should be a declaration is really a selector.
991 * If it's a selector than it's a nested selector. This support's Less' 992 * If it's a selector than it's a nested selector. This support's Less'
992 * nested selector syntax (requires a look ahead). E.g., 993 * nested selector syntax (requires a look ahead). E.g.,
993 * 994 *
994 * div { 995 * div {
995 * width : 20px; 996 * width : 20px;
996 * span { 997 * span {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 do { 1185 do {
1185 Selector selector = processSelector(); 1186 Selector selector = processSelector();
1186 if (selector != null) { 1187 if (selector != null) {
1187 selectors.add(selector); 1188 selectors.add(selector);
1188 } 1189 }
1189 } while (_maybeEat(TokenKind.COMMA)); 1190 } while (_maybeEat(TokenKind.COMMA));
1190 1191
1191 if (selectors.length > 0) { 1192 if (selectors.length > 0) {
1192 return new SelectorGroup(selectors, _makeSpan(start)); 1193 return new SelectorGroup(selectors, _makeSpan(start));
1193 } 1194 }
1195 return null;
1194 } 1196 }
1195 1197
1196 /** 1198 /**
1197 * Return list of selectors 1199 * Return list of selectors
1198 */ 1200 */
1199 Selector processSelector() { 1201 Selector processSelector() {
1200 var simpleSequences = <SimpleSelectorSequence>[]; 1202 var simpleSequences = <SimpleSelectorSequence>[];
1201 var start = _peekToken.span; 1203 var start = _peekToken.span;
1202 while (true) { 1204 while (true) {
1203 // First item is never descendant make sure it's COMBINATOR_NONE. 1205 // First item is never descendant make sure it's COMBINATOR_NONE.
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 1597
1596 if (value == null) { 1598 if (value == null) {
1597 _error('expected attribute value string or ident', _peekToken.span); 1599 _error('expected attribute value string or ident', _peekToken.span);
1598 } 1600 }
1599 } 1601 }
1600 1602
1601 _eat(TokenKind.RBRACK); 1603 _eat(TokenKind.RBRACK);
1602 1604
1603 return new AttributeSelector(attrName, op, value, _makeSpan(start)); 1605 return new AttributeSelector(attrName, op, value, _makeSpan(start));
1604 } 1606 }
1607 return null;
1605 } 1608 }
1606 1609
1607 // Declaration grammar: 1610 // Declaration grammar:
1608 // 1611 //
1609 // declaration: property ':' expr prio? 1612 // declaration: property ':' expr prio?
1610 // 1613 //
1611 // property: IDENT [or IE hacks] 1614 // property: IDENT [or IE hacks]
1612 // prio: !important 1615 // prio: !important
1613 // expr: (see processExpr) 1616 // expr: (see processExpr)
1614 // 1617 //
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1756 }; 1759 };
1757 1760
1758 static int _findStyle(String styleName) => _stylesToDart[styleName]; 1761 static int _findStyle(String styleName) => _stylesToDart[styleName];
1759 1762
1760 DartStyleExpression _styleForDart( 1763 DartStyleExpression _styleForDart(
1761 Identifier property, Expressions exprs, List dartStyles) { 1764 Identifier property, Expressions exprs, List dartStyles) {
1762 var styleType = _findStyle(property.name.toLowerCase()); 1765 var styleType = _findStyle(property.name.toLowerCase());
1763 if (styleType != null) { 1766 if (styleType != null) {
1764 return buildDartStyleNode(styleType, exprs, dartStyles); 1767 return buildDartStyleNode(styleType, exprs, dartStyles);
1765 } 1768 }
1769 return null;
1766 } 1770 }
1767 1771
1768 FontExpression _mergeFontStyles(FontExpression fontExpr, List dartStyles) { 1772 FontExpression _mergeFontStyles(FontExpression fontExpr, List dartStyles) {
1769 // Merge all font styles for this class selector. 1773 // Merge all font styles for this class selector.
1770 for (var dartStyle in dartStyles) { 1774 for (var dartStyle in dartStyles) {
1771 if (dartStyle.isFont) { 1775 if (dartStyle.isFont) {
1772 fontExpr = new FontExpression.merge(dartStyle, fontExpr); 1776 fontExpr = new FontExpression.merge(dartStyle, fontExpr);
1773 } 1777 }
1774 } 1778 }
1775 1779
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1903 case _heightPart: 1907 case _heightPart:
1904 case _widthPart: 1908 case _widthPart:
1905 case _paddingPartLeft: 1909 case _paddingPartLeft:
1906 case _paddingPartTop: 1910 case _paddingPartTop:
1907 case _paddingPartRight: 1911 case _paddingPartRight:
1908 case _paddingPartBottom: 1912 case _paddingPartBottom:
1909 if (exprs.expressions.length > 0) { 1913 if (exprs.expressions.length > 0) {
1910 return processOneNumber(exprs, styleType); 1914 return processOneNumber(exprs, styleType);
1911 } 1915 }
1912 break; 1916 break;
1913 default:
1914 // Don't handle it.
1915 return null;
1916 } 1917 }
1918 return null;
1917 } 1919 }
1918 1920
1919 // TODO(terry): Look at handling width of thin, thick, etc. any none numbers 1921 // TODO(terry): Look at handling width of thin, thick, etc. any none numbers
1920 // to convert to a number. 1922 // to convert to a number.
1921 DartStyleExpression processOneNumber(Expressions exprs, int part) { 1923 DartStyleExpression processOneNumber(Expressions exprs, int part) {
1922 var value = marginValue(exprs.expressions[0]); 1924 var value = marginValue(exprs.expressions[0]);
1923 if (value != null) { 1925 if (value != null) {
1924 switch (part) { 1926 switch (part) {
1925 case _marginPartLeft: 1927 case _marginPartLeft:
1926 return new MarginExpression(exprs.span, left: value); 1928 return new MarginExpression(exprs.span, left: value);
(...skipping 22 matching lines...) Expand all
1949 case _paddingPartLeft: 1951 case _paddingPartLeft:
1950 return new PaddingExpression(exprs.span, left: value); 1952 return new PaddingExpression(exprs.span, left: value);
1951 case _paddingPartTop: 1953 case _paddingPartTop:
1952 return new PaddingExpression(exprs.span, top: value); 1954 return new PaddingExpression(exprs.span, top: value);
1953 case _paddingPartRight: 1955 case _paddingPartRight:
1954 return new PaddingExpression(exprs.span, right: value); 1956 return new PaddingExpression(exprs.span, right: value);
1955 case _paddingPartBottom: 1957 case _paddingPartBottom:
1956 return new PaddingExpression(exprs.span, bottom: value); 1958 return new PaddingExpression(exprs.span, bottom: value);
1957 } 1959 }
1958 } 1960 }
1961 return null;
1959 } 1962 }
1960 1963
1961 /** 1964 /**
1962 * Margins are of the format: 1965 * Margins are of the format:
1963 * 1966 *
1964 * top,right,bottom,left (4 parameters) 1967 * top,right,bottom,left (4 parameters)
1965 * top,right/left, bottom (3 parameters) 1968 * top,right/left, bottom (3 parameters)
1966 * top/bottom,right/left (2 parameters) 1969 * top/bottom,right/left (2 parameters)
1967 * top/right/bottom/left (1 parameter) 1970 * top/right/bottom/left (1 parameter)
1968 * 1971 *
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
2178 _error('Expecting a positive number', _makeSpan(start)); 2181 _error('Expecting a positive number', _makeSpan(start));
2179 } 2182 }
2180 2183
2181 _eat(TokenKind.RBRACK); 2184 _eat(TokenKind.RBRACK);
2182 2185
2183 return new ItemTerm(term.value, term.text, _makeSpan(start)); 2186 return new ItemTerm(term.value, term.text, _makeSpan(start));
2184 case TokenKind.IDENTIFIER: 2187 case TokenKind.IDENTIFIER:
2185 var nameValue = identifier(); // Snarf up the ident we'll remap, maybe. 2188 var nameValue = identifier(); // Snarf up the ident we'll remap, maybe.
2186 2189
2187 if (!ieFilter && _maybeEat(TokenKind.LPAREN)) { 2190 if (!ieFilter && _maybeEat(TokenKind.LPAREN)) {
2191 var calc = processCalc(nameValue);
2192 if (calc != null) return calc;
2188 // FUNCTION 2193 // FUNCTION
2189 return processFunction(nameValue); 2194 return processFunction(nameValue);
2190 } 2195 }
2191 if (ieFilter) { 2196 if (ieFilter) {
2192 if (_maybeEat(TokenKind.COLON) && 2197 if (_maybeEat(TokenKind.COLON) &&
2193 nameValue.name.toLowerCase() == 'progid') { 2198 nameValue.name.toLowerCase() == 'progid') {
2194 // IE filter:progid: 2199 // IE filter:progid:
2195 return processIEFilter(start); 2200 return processIEFilter(start);
2196 } else { 2201 } else {
2197 // Handle filter:<name> where name is any filter e.g., alpha, chroma , 2202 // Handle filter:<name> where name is any filter e.g., alpha, chroma ,
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
2432 startAfterProgidColon.start.offset, _peekToken.start); 2437 startAfterProgidColon.start.offset, _peekToken.start);
2433 return new LiteralTerm(tok.text, tok.text, tok.span); 2438 return new LiteralTerm(tok.text, tok.text, tok.span);
2434 } 2439 }
2435 break; 2440 break;
2436 default: 2441 default:
2437 _eat(_peek()); 2442 _eat(_peek());
2438 } 2443 }
2439 } 2444 }
2440 } 2445 }
2441 2446
2447 // TODO(terry): Hack to gobble up the calc expression as a string looking
2448 // for the matching RPAREN the expression is not parsed into the
2449 // AST.
2450 //
2451 // grammar should be:
2452 //
2453 // <calc()> = calc( <calc-sum> )
2454 // <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
2455 // <calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]*
2456 // <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
2457 //
2458 String processCalcExpression() {
2459 var inString = tokenizer._inString;
2460 tokenizer._inString = false;
2461
2462 // Gobble up everything until we hit our stop token.
2463 var stringValue = new StringBuffer();
2464 var left = 1;
2465 var matchingParens = false;
2466 while (_peek() != TokenKind.END_OF_FILE && !matchingParens) {
2467 var token = _peek();
2468 if (token == TokenKind.LPAREN)
2469 left++;
2470 else if (token == TokenKind.RPAREN)
2471 left--;
2472
2473 matchingParens = left == 0;
2474 if (!matchingParens) stringValue.write(_next().text);
2475 }
2476
2477 if (!matchingParens) {
2478 _error("problem parsing function expected ), ", _peekToken.span);
2479 }
2480
2481 tokenizer._inString = inString;
2482
2483 return stringValue.toString();
2484 }
2485
2486 CalcTerm processCalc(Identifier func) {
2487 var start = _peekToken.span;
2488
2489 var name = func.name;
2490 if (name == 'calc') {
2491 // TODO(terry): Implement expression parsing properly.
2492 String expression = processCalcExpression();
2493 var calcExpr = new LiteralTerm(expression, expression, _makeSpan(start));
2494
2495 if (!_maybeEat(TokenKind.RPAREN)) {
2496 _error("problem parsing function expected ), ", _peekToken.span);
2497 }
2498
2499 return new CalcTerm(name, name, calcExpr, _makeSpan(start));
2500 }
2501
2502 return null;
2503 }
2504
2442 // Function grammar: 2505 // Function grammar:
2443 // 2506 //
2444 // function: IDENT '(' expr ')' 2507 // function: IDENT '(' expr ')'
2445 // 2508 //
2446 processFunction(Identifier func) { 2509 processFunction(Identifier func) {
2447 var start = _peekToken.span; 2510 var start = _peekToken.span;
2448 2511
2449 var name = func.name; 2512 var name = func.name;
2450 2513
2451 switch (name) { 2514 switch (name) {
2452 case 'url': 2515 case 'url':
2453 // URI term sucks up everything inside of quotes(' or ") or between pare ns 2516 // URI term sucks up everything inside of quotes(' or ") or between pare ns
2454 var urlParam = processQuotedString(true); 2517 var urlParam = processQuotedString(true);
2455 2518
2456 // TODO(terry): Better error messge and checking for mismatched quotes. 2519 // TODO(terry): Better error messge and checking for mismatched quotes.
2457 if (_peek() == TokenKind.END_OF_FILE) { 2520 if (_peek() == TokenKind.END_OF_FILE) {
2458 _error("problem parsing URI", _peekToken.span); 2521 _error("problem parsing URI", _peekToken.span);
2459 } 2522 }
2460 2523
2461 if (_peek() == TokenKind.RPAREN) { 2524 if (_peek() == TokenKind.RPAREN) {
2462 _next(); 2525 _next();
2463 } 2526 }
2464 2527
2465 return new UriTerm(urlParam, _makeSpan(start)); 2528 return new UriTerm(urlParam, _makeSpan(start));
2466 case 'calc':
2467 // TODO(terry): Implement expression handling...
2468 break;
2469 case 'var': 2529 case 'var':
2470 // TODO(terry): Consider handling var in IE specific filter/progid. Thi s 2530 // TODO(terry): Consider handling var in IE specific filter/progid. Thi s
2471 // will require parsing entire IE specific syntax e.g., 2531 // will require parsing entire IE specific syntax e.g.,
2472 // param = value or progid:com_id, etc. for example: 2532 // param = value or progid:com_id, etc. for example:
2473 // 2533 //
2474 // var-blur: Blur(Add = 0, Direction = 225, Strength = 10); 2534 // var-blur: Blur(Add = 0, Direction = 225, Strength = 10);
2475 // var-gradient: progid:DXImageTransform.Microsoft.gradient" 2535 // var-gradient: progid:DXImageTransform.Microsoft.gradient"
2476 // (GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); 2536 // (GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
2477 var expr = processExpr(); 2537 var expr = processExpr();
2478 if (!_maybeEat(TokenKind.RPAREN)) { 2538 if (!_maybeEat(TokenKind.RPAREN)) {
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2686 2746
2687 if (replace != null && result == null) { 2747 if (replace != null && result == null) {
2688 result = new StringBuffer(text.substring(0, i)); 2748 result = new StringBuffer(text.substring(0, i));
2689 } 2749 }
2690 2750
2691 if (result != null) result.write(replace != null ? replace : text[i]); 2751 if (result != null) result.write(replace != null ? replace : text[i]);
2692 } 2752 }
2693 2753
2694 return result == null ? text : result.toString(); 2754 return result == null ? text : result.toString();
2695 } 2755 }
OLDNEW
« no previous file with comments | « packages/csslib/README.md ('k') | packages/csslib/lib/src/analyzer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698