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

Side by Side Diff: tools/testing/dart/status_expression.dart

Issue 841193003: cleanup to tools/testing/dart (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: one last bit Created 5 years, 11 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
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.
4
5 library status_expression;
6
7 /**
8 * Parse and evaluate expressions in a .status file for Dart and V8.
9 * There are set expressions and Boolean expressions in a .status file.
10 * The grammar is:
11 * BooleanExpression := $variableName == value | $variableName != value |
12 * $variableName | (BooleanExpression) |
13 * BooleanExpression && BooleanExpression |
14 * BooleanExpression || BooleanExpression
15 *
16 * SetExpression := value | (SetExpression) |
17 * SetExpression || SetExpression |
18 * SetExpression if BooleanExpression |
19 * SetExpression , SetExpression
20 *
21 * Productions are listed in order of precedence, and the || and , operators
22 * both evaluate to set union, but with different precedence.
23 *
24 * Values and variableNames are non-empty strings of word characters, matching
25 * the RegExp \w+.
26 *
27 * Expressions evaluate as expected, with values of variables found in
28 * an environment passed to the evaluator. The SetExpression "value"
29 * evaluates to a singleton set containing that value. "A if B" evaluates
30 * to A if B is true, and to the empty set if B is false.
31 */
32
33 class ExprEvaluationException {
34 String error;
35
36 ExprEvaluationException(this.error);
37
38 toString() => error;
39 }
40
41 class Token {
42 static const String LEFT_PAREN = "(";
43 static const String RIGHT_PAREN = ")";
44 static const String DOLLAR_SYMBOL = r"$";
45 static const String UNION = ",";
46 static const String EQUALS = "==";
47 static const String NOT_EQUALS = "!=";
48 static const String AND = "&&";
49 static const String OR = "||";
50 }
51
52
53 class Tokenizer {
54 String expression;
55 List<String> tokens;
56
57 Tokenizer(String this.expression)
58 : tokens = new List<String>();
59
60 // Tokens are : "(", ")", "$", ",", "&&", "||", "==", "!=", and (maximal) \w+.
61 static final testRegexp =
62 new RegExp(r"^([()$\w\s,]|(\&\&)|(\|\|)|(\=\=)|(\!\=))+$");
63 static final regexp = new RegExp(r"[()$,]|(\&\&)|(\|\|)|(\=\=)|(\!\=)|\w+");
64
65 List<String> tokenize() {
66 if (!testRegexp.hasMatch(expression)) {
67 throw new FormatException("Syntax error in '$expression'");
68 }
69 for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
70 return tokens;
71 }
72 }
73
74
75 abstract class BooleanExpression {
76 bool evaluate(Map<String, String> environment);
77 }
78
79
80 abstract class SetExpression {
81 Set<String> evaluate(Map<String, String> environment);
82 }
83
84
85 class Comparison implements BooleanExpression {
86 TermVariable left;
87 TermConstant right;
88 bool negate;
89
90 Comparison(this.left, this.right, this.negate);
91
92 bool evaluate(environment) {
93 return
94 negate != (left.termValue(environment) == right.termValue(environment));
95 }
96
97 String toString() =>
98 "(\$${left.name} ${negate ? '!=' : '=='} ${right.value})";
99 }
100
101
102 class TermVariable {
103 String name;
104
105 TermVariable(this.name);
106
107 String termValue(environment) {
108 var value = environment[name];
109 if (value == null) {
110 throw new ExprEvaluationException(
111 "Could not find '$name' in environment "
112 "while evaluating status file expression.");
113 }
114 return value.toString();
115 }
116 }
117
118
119 class TermConstant {
120 String value;
121
122 TermConstant(String this.value);
123
124 String termValue(environment) => value;
125 }
126
127
128 class BooleanVariable implements BooleanExpression {
129 TermVariable variable;
130
131 BooleanVariable(this.variable);
132
133 bool evaluate(environment) => variable.termValue(environment) == 'true';
134 String toString() => "(bool \$${variable.name})";
135 }
136
137
138 class BooleanOperation implements BooleanExpression {
139 String op;
140 BooleanExpression left;
141 BooleanExpression right;
142
143 BooleanOperation(this.op, this.left, this.right);
144
145 bool evaluate(environment) => (op == Token.AND) ?
146 left.evaluate(environment) && right.evaluate(environment) :
147 left.evaluate(environment) || right.evaluate(environment);
148 String toString() => "($left $op $right)";
149 }
150
151
152 class SetUnion implements SetExpression {
153 SetExpression left;
154 SetExpression right;
155
156 SetUnion(this.left, this.right);
157
158 // Overwrites left.evaluate(env).
159 // Set.addAll does not return this.
160 Set<String> evaluate(environment) {
161 Set<String> result = left.evaluate(environment);
162 result.addAll(right.evaluate(environment));
163 return result;
164 }
165
166 String toString() => "($left || $right)";
167 }
168
169
170 class SetIf implements SetExpression {
171 SetExpression left;
172 BooleanExpression right;
173
174 SetIf(this.left, this.right);
175
176 Set<String> evaluate(environment) => right.evaluate(environment) ?
177 left.evaluate(environment) : new Set<String>();
178 String toString() => "($left if $right)";
179 }
180
181
182 class SetConstant implements SetExpression {
183 String value;
184
185 SetConstant(String v) : value = v.toLowerCase();
186
187 Set<String> evaluate(environment) => new Set<String>.from([value]);
188 String toString() => value;
189 }
190
191
192 // An iterator that allows peeking at the current token.
193 class Scanner {
194 List<String> tokens;
195 Iterator tokenIterator;
196 String current;
197
198 Scanner(this.tokens) {
199 tokenIterator = tokens.iterator;
200 advance();
201 }
202
203 bool hasMore() => current != null;
204
205 void advance() {
206 current = tokenIterator.moveNext() ? tokenIterator.current : null;
207 }
208 }
209
210
211 class ExpressionParser {
212 Scanner scanner;
213
214 ExpressionParser(this.scanner);
215
216 SetExpression parseSetExpression() => parseSetUnion();
217
218 SetExpression parseSetUnion() {
219 SetExpression left = parseSetIf();
220 while (scanner.hasMore() && scanner.current == Token.UNION){
221 scanner.advance();
222 SetExpression right = parseSetIf();
223 left = new SetUnion(left, right);
224 }
225 return left;
226 }
227
228 SetExpression parseSetIf() {
229 SetExpression left = parseSetOr();
230 while (scanner.hasMore() && scanner.current == "if") {
231 scanner.advance();
232 BooleanExpression right = parseBooleanExpression();
233 left = new SetIf(left, right);
234 }
235 return left;
236 }
237
238 SetExpression parseSetOr() {
239 SetExpression left = parseSetAtomic();
240 while (scanner.hasMore() && scanner.current == Token.OR){
241 scanner.advance();
242 SetExpression right = parseSetAtomic();
243 left = new SetUnion(left, right);
244 }
245 return left;
246 }
247
248
249 SetExpression parseSetAtomic() {
250 if (scanner.current == Token.LEFT_PAREN) {
251 scanner.advance();
252 SetExpression value = parseSetExpression();
253 if (scanner.current != Token.RIGHT_PAREN) {
254 throw new FormatException("Missing right parenthesis in expression");
255 }
256 scanner.advance();
257 return value;
258 }
259 if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
260 throw new FormatException(
261 "Expected identifier in expression, got ${scanner.current}");
262 }
263 SetExpression value = new SetConstant(scanner.current);
264 scanner.advance();
265 return value;
266 }
267
268 BooleanExpression parseBooleanExpression() => parseBooleanOr();
269
270 BooleanExpression parseBooleanOr() {
271 BooleanExpression left = parseBooleanAnd();
272 while (scanner.hasMore() && scanner.current == Token.OR) {
273 scanner.advance();
274 BooleanExpression right = parseBooleanAnd();
275 left = new BooleanOperation(Token.OR, left, right);
276 }
277 return left;
278 }
279
280 BooleanExpression parseBooleanAnd() {
281 BooleanExpression left = parseBooleanAtomic();
282 while (scanner.hasMore() && scanner.current == Token.AND) {
283 scanner.advance();
284 BooleanExpression right = parseBooleanAtomic();
285 left = new BooleanOperation(Token.AND, left, right);
286 }
287 return left;
288 }
289
290 BooleanExpression parseBooleanAtomic() {
291 if (scanner.current == Token.LEFT_PAREN) {
292 scanner.advance();
293 BooleanExpression value = parseBooleanExpression();
294 if (scanner.current != Token.RIGHT_PAREN) {
295 throw new FormatException("Missing right parenthesis in expression");
296 }
297 scanner.advance();
298 return value;
299 }
300
301 // The only atomic booleans are of the form $variable == value or
302 // of the form $variable.
303 if (scanner.current != Token.DOLLAR_SYMBOL) {
304 throw new FormatException(
305 "Expected \$ in expression, got ${scanner.current}");
306 }
307 scanner.advance();
308 if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
309 throw new FormatException(
310 "Expected identifier in expression, got ${scanner.current}");
311 }
312 TermVariable left = new TermVariable(scanner.current);
313 scanner.advance();
314 if (scanner.current == Token.EQUALS ||
315 scanner.current == Token.NOT_EQUALS) {
316 bool negate = scanner.current == Token.NOT_EQUALS;
317 scanner.advance();
318 if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
319 throw new FormatException(
320 "Expected value in expression, got ${scanner.current}");
321 }
322 TermConstant right = new TermConstant(scanner.current);
323 scanner.advance();
324 return new Comparison(left, right, negate);
325 } else {
326 return new BooleanVariable(left);
327 }
328 }
329 }
330
OLDNEW
« no previous file with comments | « tools/testing/dart/runtime_configuration.dart ('k') | tools/testing/dart/status_file_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698