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

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

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

Powered by Google App Engine
This is Rietveld 408576698