Chromium Code Reviews| 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 2170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2181 _error('Expecting a positive number', _makeSpan(start)); | 2181 _error('Expecting a positive number', _makeSpan(start)); |
| 2182 } | 2182 } |
| 2183 | 2183 |
| 2184 _eat(TokenKind.RBRACK); | 2184 _eat(TokenKind.RBRACK); |
| 2185 | 2185 |
| 2186 return new ItemTerm(term.value, term.text, _makeSpan(start)); | 2186 return new ItemTerm(term.value, term.text, _makeSpan(start)); |
| 2187 case TokenKind.IDENTIFIER: | 2187 case TokenKind.IDENTIFIER: |
| 2188 var nameValue = identifier(); // Snarf up the ident we'll remap, maybe. | 2188 var nameValue = identifier(); // Snarf up the ident we'll remap, maybe. |
| 2189 | 2189 |
| 2190 if (!ieFilter && _maybeEat(TokenKind.LPAREN)) { | 2190 if (!ieFilter && _maybeEat(TokenKind.LPAREN)) { |
| 2191 var calc = processCalc(nameValue); | |
| 2192 if (calc != null) return calc; | |
| 2191 // FUNCTION | 2193 // FUNCTION |
| 2192 return processFunction(nameValue); | 2194 return processFunction(nameValue); |
| 2193 } | 2195 } |
| 2194 if (ieFilter) { | 2196 if (ieFilter) { |
| 2195 if (_maybeEat(TokenKind.COLON) && | 2197 if (_maybeEat(TokenKind.COLON) && |
| 2196 nameValue.name.toLowerCase() == 'progid') { | 2198 nameValue.name.toLowerCase() == 'progid') { |
| 2197 // IE filter:progid: | 2199 // IE filter:progid: |
| 2198 return processIEFilter(start); | 2200 return processIEFilter(start); |
| 2199 } else { | 2201 } else { |
| 2200 // 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 Loading... | |
| 2435 startAfterProgidColon.start.offset, _peekToken.start); | 2437 startAfterProgidColon.start.offset, _peekToken.start); |
| 2436 return new LiteralTerm(tok.text, tok.text, tok.span); | 2438 return new LiteralTerm(tok.text, tok.text, tok.span); |
| 2437 } | 2439 } |
| 2438 break; | 2440 break; |
| 2439 default: | 2441 default: |
| 2440 _eat(_peek()); | 2442 _eat(_peek()); |
| 2441 } | 2443 } |
| 2442 } | 2444 } |
| 2443 } | 2445 } |
| 2444 | 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 start = _peekToken.span; | |
|
kevmoo
2015/10/16 17:56:39
start seems to not be used
terry
2015/10/16 18:28:46
Right, not used now but will be when fully parsed.
| |
| 2460 | |
| 2461 var inString = tokenizer._inString; | |
| 2462 tokenizer._inString = false; | |
| 2463 | |
| 2464 // Gobble up everything until we hit our stop token. | |
| 2465 var stringValue = new StringBuffer(); | |
| 2466 var left = 1; | |
| 2467 var matchingParens = false; | |
| 2468 while (_peek() != TokenKind.END_OF_FILE && !matchingParens) { | |
| 2469 var token = _peek(); | |
| 2470 if (token == TokenKind.LPAREN) | |
| 2471 left++; | |
| 2472 else if (token == TokenKind.RPAREN) | |
| 2473 left--; | |
| 2474 | |
| 2475 matchingParens = left == 0; | |
| 2476 if (!matchingParens) stringValue.write(_next().text); | |
| 2477 } | |
| 2478 | |
| 2479 if (!matchingParens) { | |
| 2480 _error("problem parsing function expected ), ", _peekToken.span); | |
| 2481 } | |
| 2482 | |
| 2483 tokenizer._inString = inString; | |
| 2484 | |
| 2485 return stringValue.toString(); | |
| 2486 } | |
| 2487 | |
| 2488 processCalc(Identifier func) { | |
|
yjbanov
2015/10/16 17:39:55
missing return type
terry
2015/10/16 18:28:46
Done.
| |
| 2489 var start = _peekToken.span; | |
| 2490 | |
| 2491 var name = func.name; | |
| 2492 if (name == 'calc') { | |
| 2493 // TODO(terry): Implement expression parsing properly. | |
| 2494 String expression = processCalcExpression(); | |
| 2495 var calcExpr = new LiteralTerm(expression, expression, _makeSpan(start)); | |
| 2496 | |
| 2497 if (!_maybeEat(TokenKind.RPAREN)) { | |
| 2498 _error("problem parsing function expected ), ", _peekToken.span); | |
| 2499 } | |
| 2500 | |
| 2501 return new CalcTerm(name, name, calcExpr, _makeSpan(start)); | |
| 2502 } | |
| 2503 | |
| 2504 return null; | |
| 2505 } | |
| 2506 | |
| 2445 // Function grammar: | 2507 // Function grammar: |
| 2446 // | 2508 // |
| 2447 // function: IDENT '(' expr ')' | 2509 // function: IDENT '(' expr ')' |
| 2448 // | 2510 // |
| 2449 processFunction(Identifier func) { | 2511 processFunction(Identifier func) { |
| 2450 var start = _peekToken.span; | 2512 var start = _peekToken.span; |
| 2451 | 2513 |
| 2452 var name = func.name; | 2514 var name = func.name; |
| 2453 | 2515 |
| 2454 switch (name) { | 2516 switch (name) { |
| 2455 case 'url': | 2517 case 'url': |
| 2456 // URI term sucks up everything inside of quotes(' or ") or between pare ns | 2518 // URI term sucks up everything inside of quotes(' or ") or between pare ns |
| 2457 var urlParam = processQuotedString(true); | 2519 var urlParam = processQuotedString(true); |
| 2458 | 2520 |
| 2459 // TODO(terry): Better error messge and checking for mismatched quotes. | 2521 // TODO(terry): Better error messge and checking for mismatched quotes. |
| 2460 if (_peek() == TokenKind.END_OF_FILE) { | 2522 if (_peek() == TokenKind.END_OF_FILE) { |
| 2461 _error("problem parsing URI", _peekToken.span); | 2523 _error("problem parsing URI", _peekToken.span); |
| 2462 } | 2524 } |
| 2463 | 2525 |
| 2464 if (_peek() == TokenKind.RPAREN) { | 2526 if (_peek() == TokenKind.RPAREN) { |
| 2465 _next(); | 2527 _next(); |
| 2466 } | 2528 } |
| 2467 | 2529 |
| 2468 return new UriTerm(urlParam, _makeSpan(start)); | 2530 return new UriTerm(urlParam, _makeSpan(start)); |
| 2469 case 'calc': | |
| 2470 // TODO(terry): Implement expression handling... | |
| 2471 break; | |
| 2472 case 'var': | 2531 case 'var': |
| 2473 // TODO(terry): Consider handling var in IE specific filter/progid. Thi s | 2532 // TODO(terry): Consider handling var in IE specific filter/progid. Thi s |
| 2474 // will require parsing entire IE specific syntax e.g., | 2533 // will require parsing entire IE specific syntax e.g., |
| 2475 // param = value or progid:com_id, etc. for example: | 2534 // param = value or progid:com_id, etc. for example: |
| 2476 // | 2535 // |
| 2477 // var-blur: Blur(Add = 0, Direction = 225, Strength = 10); | 2536 // var-blur: Blur(Add = 0, Direction = 225, Strength = 10); |
| 2478 // var-gradient: progid:DXImageTransform.Microsoft.gradient" | 2537 // var-gradient: progid:DXImageTransform.Microsoft.gradient" |
| 2479 // (GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); | 2538 // (GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); |
| 2480 var expr = processExpr(); | 2539 var expr = processExpr(); |
| 2481 if (!_maybeEat(TokenKind.RPAREN)) { | 2540 if (!_maybeEat(TokenKind.RPAREN)) { |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2689 | 2748 |
| 2690 if (replace != null && result == null) { | 2749 if (replace != null && result == null) { |
| 2691 result = new StringBuffer(text.substring(0, i)); | 2750 result = new StringBuffer(text.substring(0, i)); |
| 2692 } | 2751 } |
| 2693 | 2752 |
| 2694 if (result != null) result.write(replace != null ? replace : text[i]); | 2753 if (result != null) result.write(replace != null ? replace : text[i]); |
| 2695 } | 2754 } |
| 2696 | 2755 |
| 2697 return result == null ? text : result.toString(); | 2756 return result == null ? text : result.toString(); |
| 2698 } | 2757 } |
| OLD | NEW |