| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 test.backend.platform_selector.scanner; | 5 library test.backend.platform_selector.scanner; |
| 6 | 6 |
| 7 import 'package:string_scanner/string_scanner.dart'; | 7 import 'package:string_scanner/string_scanner.dart'; |
| 8 | 8 |
| 9 import '../../utils.dart'; |
| 9 import 'token.dart'; | 10 import 'token.dart'; |
| 10 | 11 |
| 11 /// A regular expression matching both whitespace and single-line comments. | 12 /// A regular expression matching both whitespace and single-line comments. |
| 12 /// | 13 /// |
| 13 /// This will only match if consumes at least one character. | 14 /// This will only match if consumes at least one character. |
| 14 final _whitespaceAndSingleLineComments = | 15 final _whitespaceAndSingleLineComments = |
| 15 new RegExp(r"([ \t\n]+|//[^\n]*(\n|$))+"); | 16 new RegExp(r"([ \t\n]+|//[^\n]*(\n|$))+"); |
| 16 | 17 |
| 17 /// A regular expression matching the body of a multi-line comment, after `/*` | 18 /// A regular expression matching the body of a multi-line comment, after `/*` |
| 18 /// but before `*/` or a nested `/*`. | 19 /// but before `*/` or a nested `/*`. |
| 19 /// | 20 /// |
| 20 /// This will only match if it consumes at least one character. | 21 /// This will only match if it consumes at least one character. |
| 21 final _multiLineCommentBody = new RegExp(r"([^/*]|/[^*]|\*[^/])+"); | 22 final _multiLineCommentBody = new RegExp(r"([^/*]|/[^*]|\*[^/])+"); |
| 22 | 23 |
| 23 /// A regular expression matching an identifier. | |
| 24 /// | |
| 25 /// Unlike standard Dart identifiers, platform selector identifiers may | |
| 26 /// contain dashes for consistency with command-line arguments. | |
| 27 final _identifier = new RegExp(r"[a-zA-Z_-][a-zA-Z0-9_-]*"); | |
| 28 | |
| 29 /// A scanner that converts a platform selector string into a stream of | 24 /// A scanner that converts a platform selector string into a stream of |
| 30 /// tokens. | 25 /// tokens. |
| 31 class Scanner { | 26 class Scanner { |
| 32 /// The underlying string scanner. | 27 /// The underlying string scanner. |
| 33 final SpanScanner _scanner; | 28 final SpanScanner _scanner; |
| 34 | 29 |
| 35 /// The next token to emit. | 30 /// The next token to emit. |
| 36 Token _next; | 31 Token _next; |
| 37 | 32 |
| 38 /// Whether the scanner has emitted a [TokenType.endOfFile] token. | 33 /// Whether the scanner has emitted a [TokenType.endOfFile] token. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 /// | 112 /// |
| 118 /// This validates that the next two characters are `&&`. | 113 /// This validates that the next two characters are `&&`. |
| 119 Token _scanAnd() { | 114 Token _scanAnd() { |
| 120 var start = _scanner.state; | 115 var start = _scanner.state; |
| 121 _scanner.expect("&&"); | 116 _scanner.expect("&&"); |
| 122 return new Token(TokenType.and, _scanner.spanFrom(start)); | 117 return new Token(TokenType.and, _scanner.spanFrom(start)); |
| 123 } | 118 } |
| 124 | 119 |
| 125 /// Scans and returns an identifier token. | 120 /// Scans and returns an identifier token. |
| 126 Token _scanIdentifier() { | 121 Token _scanIdentifier() { |
| 127 _scanner.expect(_identifier, name: "expression"); | 122 _scanner.expect(hyphenatedIdentifier, name: "expression"); |
| 128 return new IdentifierToken(_scanner.lastMatch[0], _scanner.lastSpan); | 123 return new IdentifierToken(_scanner.lastMatch[0], _scanner.lastSpan); |
| 129 } | 124 } |
| 130 | 125 |
| 131 /// Consumes all whitespace and comments immediately following the cursor's | 126 /// Consumes all whitespace and comments immediately following the cursor's |
| 132 /// current position. | 127 /// current position. |
| 133 void _consumeWhitespace() { | 128 void _consumeWhitespace() { |
| 134 while (_scanner.scan(_whitespaceAndSingleLineComments) || | 129 while (_scanner.scan(_whitespaceAndSingleLineComments) || |
| 135 _multiLineComment()) { | 130 _multiLineComment()) { |
| 136 // Do nothing. | 131 // Do nothing. |
| 137 } | 132 } |
| 138 } | 133 } |
| 139 | 134 |
| 140 /// Consumes a single multi-line comment. | 135 /// Consumes a single multi-line comment. |
| 141 /// | 136 /// |
| 142 /// Returns whether or not a comment was consumed. | 137 /// Returns whether or not a comment was consumed. |
| 143 bool _multiLineComment() { | 138 bool _multiLineComment() { |
| 144 if (!_scanner.scan("/*")) return false; | 139 if (!_scanner.scan("/*")) return false; |
| 145 | 140 |
| 146 while (_scanner.scan(_multiLineCommentBody) || _multiLineComment()) { | 141 while (_scanner.scan(_multiLineCommentBody) || _multiLineComment()) { |
| 147 // Do nothing. | 142 // Do nothing. |
| 148 } | 143 } |
| 149 _scanner.expect("*/"); | 144 _scanner.expect("*/"); |
| 150 | 145 |
| 151 return true; | 146 return true; |
| 152 } | 147 } |
| 153 } | 148 } |
| OLD | NEW |