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

Side by Side Diff: packages/glob/lib/src/parser.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 months 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/glob/lib/src/list_tree.dart ('k') | packages/glob/lib/src/stream_pool.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 glob.single_component;
6
7 import 'package:path/path.dart' as p; 5 import 'package:path/path.dart' as p;
8 import 'package:string_scanner/string_scanner.dart'; 6 import 'package:string_scanner/string_scanner.dart';
9 7
10 import 'ast.dart'; 8 import 'ast.dart';
11 import 'utils.dart'; 9 import 'utils.dart';
12 10
13 const _HYPHEN = 0x2D; 11 const _HYPHEN = 0x2D;
14 const _SLASH = 0x2F; 12 const _SLASH = 0x2F;
15 13
16 /// A parser for globs. 14 /// A parser for globs.
17 class Parser { 15 class Parser {
18 /// The scanner used to scan the source. 16 /// The scanner used to scan the source.
19 final StringScanner _scanner; 17 final StringScanner _scanner;
20 18
21 /// The path context for the glob. 19 /// The path context for the glob.
22 final p.Context _context; 20 final p.Context _context;
23 21
24 Parser(String component, this._context) 22 /// Whether this glob is case-sensitive.
25 : _scanner = new StringScanner(component); 23 final bool _caseSensitive;
24
25 Parser(String component, this._context, {bool caseSensitive: true})
26 : _scanner = new StringScanner(component),
27 _caseSensitive = caseSensitive;
26 28
27 /// Parses an entire glob. 29 /// Parses an entire glob.
28 SequenceNode parse() => _parseSequence(); 30 SequenceNode parse() => _parseSequence();
29 31
30 /// Parses a [SequenceNode]. 32 /// Parses a [SequenceNode].
31 /// 33 ///
32 /// If [inOptions] is true, this is parsing within an [OptionsNode]. 34 /// If [inOptions] is true, this is parsing within an [OptionsNode].
33 SequenceNode _parseSequence({bool inOptions: false}) { 35 SequenceNode _parseSequence({bool inOptions: false}) {
34 var nodes = []; 36 var nodes = <AstNode>[];
35 37
36 if (_scanner.isDone) { 38 if (_scanner.isDone) {
37 _scanner.error('expected a glob.', position: 0, length: 0); 39 _scanner.error('expected a glob.', position: 0, length: 0);
38 } 40 }
39 41
40 while (!_scanner.isDone) { 42 while (!_scanner.isDone) {
41 if (inOptions && (_scanner.matches(',') || _scanner.matches('}'))) break; 43 if (inOptions && (_scanner.matches(',') || _scanner.matches('}'))) break;
42 nodes.add(_parseNode(inOptions: inOptions)); 44 nodes.add(_parseNode(inOptions: inOptions));
43 } 45 }
44 46
45 return new SequenceNode(nodes); 47 return new SequenceNode(nodes, caseSensitive: _caseSensitive);
46 } 48 }
47 49
48 /// Parses an [AstNode]. 50 /// Parses an [AstNode].
49 /// 51 ///
50 /// If [inOptions] is true, this is parsing within an [OptionsNode]. 52 /// If [inOptions] is true, this is parsing within an [OptionsNode].
51 AstNode _parseNode({bool inOptions: false}) { 53 AstNode _parseNode({bool inOptions: false}) {
52 var star = _parseStar(); 54 var star = _parseStar();
53 if (star != null) return star; 55 if (star != null) return star;
54 56
55 var anyChar = _parseAnyChar(); 57 var anyChar = _parseAnyChar();
56 if (anyChar != null) return anyChar; 58 if (anyChar != null) return anyChar;
57 59
58 var range = _parseRange(); 60 var range = _parseRange();
59 if (range != null) return range; 61 if (range != null) return range;
60 62
61 var options = _parseOptions(); 63 var options = _parseOptions();
62 if (options != null) return options; 64 if (options != null) return options;
63 65
64 return _parseLiteral(inOptions: inOptions); 66 return _parseLiteral(inOptions: inOptions);
65 } 67 }
66 68
67 /// Tries to parse a [StarNode] or a [DoubleStarNode]. 69 /// Tries to parse a [StarNode] or a [DoubleStarNode].
68 /// 70 ///
69 /// Returns `null` if there's not one to parse. 71 /// Returns `null` if there's not one to parse.
70 AstNode _parseStar() { 72 AstNode _parseStar() {
71 if (!_scanner.scan('*')) return null; 73 if (!_scanner.scan('*')) return null;
72 return _scanner.scan('*') ? new DoubleStarNode(_context) : new StarNode(); 74 return _scanner.scan('*')
75 ? new DoubleStarNode(_context, caseSensitive: _caseSensitive)
76 : new StarNode(caseSensitive: _caseSensitive);
73 } 77 }
74 78
75 /// Tries to parse an [AnyCharNode]. 79 /// Tries to parse an [AnyCharNode].
76 /// 80 ///
77 /// Returns `null` if there's not one to parse. 81 /// Returns `null` if there's not one to parse.
78 AstNode _parseAnyChar() { 82 AstNode _parseAnyChar() {
79 if (!_scanner.scan('?')) return null; 83 if (!_scanner.scan('?')) return null;
80 return new AnyCharNode(); 84 return new AnyCharNode(caseSensitive: _caseSensitive);
81 } 85 }
82 86
83 /// Tries to parse an [RangeNode]. 87 /// Tries to parse an [RangeNode].
84 /// 88 ///
85 /// Returns `null` if there's not one to parse. 89 /// Returns `null` if there's not one to parse.
86 AstNode _parseRange() { 90 AstNode _parseRange() {
87 if (!_scanner.scan('[')) return null; 91 if (!_scanner.scan('[')) return null;
88 if (_scanner.matches(']')) _scanner.error('unexpected "]".'); 92 if (_scanner.matches(']')) _scanner.error('unexpected "]".');
89 var negated = _scanner.scan('!') || _scanner.scan('^'); 93 var negated = _scanner.scan('!') || _scanner.scan('^');
90 94
91 readRangeChar() { 95 readRangeChar() {
92 var char = _scanner.readChar(); 96 var char = _scanner.readChar();
93 if (negated || char != _SLASH) return char; 97 if (negated || char != _SLASH) return char;
94 _scanner.error('"/" may not be used in a range.', 98 _scanner.error('"/" may not be used in a range.',
95 position: _scanner.position - 1); 99 position: _scanner.position - 1);
96 } 100 }
97 101
98 var ranges = []; 102 var ranges = <Range>[];
99 while (!_scanner.scan(']')) { 103 while (!_scanner.scan(']')) {
100 var start = _scanner.position; 104 var start = _scanner.position;
101 // Allow a backslash to escape a character. 105 // Allow a backslash to escape a character.
102 _scanner.scan('\\'); 106 _scanner.scan('\\');
103 var char = readRangeChar(); 107 var char = readRangeChar();
104 108
105 if (_scanner.scan('-')) { 109 if (_scanner.scan('-')) {
106 if (_scanner.matches(']')) { 110 if (_scanner.matches(']')) {
107 ranges.add(new Range.singleton(char)); 111 ranges.add(new Range.singleton(char));
108 ranges.add(new Range.singleton(_HYPHEN)); 112 ranges.add(new Range.singleton(_HYPHEN));
109 continue; 113 continue;
110 } 114 }
111 115
112 // Allow a backslash to escape a character. 116 // Allow a backslash to escape a character.
113 _scanner.scan('\\'); 117 _scanner.scan('\\');
114 118
115 var end = readRangeChar(); 119 var end = readRangeChar();
116 120
117 if (end < char) { 121 if (end < char) {
118 _scanner.error("Range out of order.", 122 _scanner.error("Range out of order.",
119 position: start, 123 position: start,
120 length: _scanner.position - start); 124 length: _scanner.position - start);
121 } 125 }
122 ranges.add(new Range(char, end)); 126 ranges.add(new Range(char, end));
123 } else { 127 } else {
124 ranges.add(new Range.singleton(char)); 128 ranges.add(new Range.singleton(char));
125 } 129 }
126 } 130 }
127 131
128 return new RangeNode(ranges, negated: negated); 132 return new RangeNode(ranges,
133 negated: negated, caseSensitive: _caseSensitive);
129 } 134 }
130 135
131 /// Tries to parse an [OptionsNode]. 136 /// Tries to parse an [OptionsNode].
132 /// 137 ///
133 /// Returns `null` if there's not one to parse. 138 /// Returns `null` if there's not one to parse.
134 AstNode _parseOptions() { 139 AstNode _parseOptions() {
135 if (!_scanner.scan('{')) return null; 140 if (!_scanner.scan('{')) return null;
136 if (_scanner.matches('}')) _scanner.error('unexpected "}".'); 141 if (_scanner.matches('}')) _scanner.error('unexpected "}".');
137 142
138 var options = []; 143 var options = <SequenceNode>[];
139 do { 144 do {
140 options.add(_parseSequence(inOptions: true)); 145 options.add(_parseSequence(inOptions: true));
141 } while (_scanner.scan(',')); 146 } while (_scanner.scan(','));
142 147
143 // Don't allow single-option blocks. 148 // Don't allow single-option blocks.
144 if (options.length == 1) _scanner.expect(','); 149 if (options.length == 1) _scanner.expect(',');
145 _scanner.expect('}'); 150 _scanner.expect('}');
146 151
147 return new OptionsNode(options); 152 return new OptionsNode(options, caseSensitive: _caseSensitive);
148 } 153 }
149 154
150 /// Parses a [LiteralNode]. 155 /// Parses a [LiteralNode].
151 AstNode _parseLiteral({bool inOptions: false}) { 156 AstNode _parseLiteral({bool inOptions: false}) {
152 // If we're in an options block, we want to stop parsing as soon as we hit a 157 // If we're in an options block, we want to stop parsing as soon as we hit a
153 // comma. Otherwise, commas are fair game for literals. 158 // comma. Otherwise, commas are fair game for literals.
154 var regExp = new RegExp( 159 var regExp = new RegExp(
155 inOptions ? r'[^*{[?\\}\],()]*' : r'[^*{[?\\}\]()]*'); 160 inOptions ? r'[^*{[?\\}\],()]*' : r'[^*{[?\\}\]()]*');
156 161
157 _scanner.scan(regExp); 162 _scanner.scan(regExp);
158 var buffer = new StringBuffer()..write(_scanner.lastMatch[0]); 163 var buffer = new StringBuffer()..write(_scanner.lastMatch[0]);
159 164
160 while (_scanner.scan('\\')) { 165 while (_scanner.scan('\\')) {
161 buffer.writeCharCode(_scanner.readChar()); 166 buffer.writeCharCode(_scanner.readChar());
162 _scanner.scan(regExp); 167 _scanner.scan(regExp);
163 buffer.write(_scanner.lastMatch[0]); 168 buffer.write(_scanner.lastMatch[0]);
164 } 169 }
165 170
166 for (var char in const [']', '(', ')']) { 171 for (var char in const [']', '(', ')']) {
167 if (_scanner.matches(char)) _scanner.error('unexpected "$char"'); 172 if (_scanner.matches(char)) _scanner.error('unexpected "$char"');
168 } 173 }
169 if (!inOptions && _scanner.matches('}')) _scanner.error('unexpected "}"'); 174 if (!inOptions && _scanner.matches('}')) _scanner.error('unexpected "}"');
170 175
171 return new LiteralNode(buffer.toString(), _context); 176 return new LiteralNode(buffer.toString(),
177 context: _context, caseSensitive: _caseSensitive);
172 } 178 }
173 } 179 }
OLDNEW
« no previous file with comments | « packages/glob/lib/src/list_tree.dart ('k') | packages/glob/lib/src/stream_pool.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698