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

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

Issue 8394043: Start adding files for Dart version of test script test.py. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rename file Created 9 years, 1 month 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
« no previous file with comments | « tests/standalone/src/StatusExpressionTest.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 |
12 * (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
34 class Token
35 {
36 static final String LEFT_PAREN = "(";
37 static final String RIGHT_PAREN = ")";
38 static final String DOLLAR_SYMBOL = @"$";
39 static final String UNION = ",";
40 static final String EQUALS = "==";
41 static final String AND = "&&";
42 static final String OR = "||";
43 }
44
45
46 class Tokenizer {
47 String expression;
48 List<String> tokens;
49
50 Tokenizer(String this.expression)
51 : tokens = new List<String>();
52
53 // Tokens are : "(", ")", "$", ",", "&&", "||", "==", and (maximal) \w+.
54 static final testRegexp =
55 const RegExp(@"^([()$\w\s,]|(\&\&)|(\|\|)|(\=\=))+$");
56 static final regexp = const RegExp(@"[()$,]|(\&\&)|(\|\|)|(\=\=)|\w+");
57
58 List<String> tokenize() {
59 if (!testRegexp.hasMatch(expression)) {
60 throw new ExpectException("Syntax error in '$expression'");
61 }
62 for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
63 return tokens;
64 }
65 }
66
67
68 interface BooleanExpression {
69 bool evaluate(Map<String, String> environment);
70 }
71
72
73 interface SetExpression {
74 Set<String> evaluate(Map<String, String> environment);
75 }
76
77
78 class Comparison implements BooleanExpression {
79 TermVariable left;
80 TermConstant right;
81
82 Comparison(this.left, this.right);
83
84 bool evaluate(environment) =>
85 left.termValue(environment) == right.termValue(environment);
86 String toString() => "(\$${left.name} == ${right.value})";
87 }
88
89
90 class TermVariable {
91 String name;
92
93 TermVariable(this.name);
94
95 String termValue(environment) => environment[name];
96 }
97
98
99 class TermConstant {
100 String value;
101
102 TermConstant(String this.value);
103
104 String termValue(environment) => value;
105 }
106
107
108 class BooleanVariable implements BooleanExpression {
109 TermVariable variable;
110
111 BooleanVariable(this.variable);
112
113 bool evaluate(environment) => variable.termValue(environment) == "true";
114 String toString() => "(bool \$${variable.name})";
115 }
116
117
118 class BooleanOperation implements BooleanExpression {
119 String op;
120 BooleanExpression left;
121 BooleanExpression right;
122
123 BooleanOperation(this.op, this.left, this.right);
124
125 bool evaluate(environment) => (op == Token.AND) ?
126 left.evaluate(environment) && right.evaluate(environment) :
127 left.evaluate(environment) || right.evaluate(environment);
128 String toString() => "($left $op $right)";
129 }
130
131
132 class SetUnion implements SetExpression {
133 SetExpression left;
134 SetExpression right;
135
136 SetUnion(this.left, this.right);
137
138 // Overwrites left.evaluate(env).
139 // Set.addAll does not return this.
140 Set<String> evaluate(environment) {
141 Set<String> result = left.evaluate(environment);
142 result.addAll(right.evaluate(environment));
143 return result;
144 }
145
146 String toString() => "($left || $right)";
147 }
148
149
150 class SetIf implements SetExpression {
151 SetExpression left;
152 BooleanExpression right;
153
154 SetIf(this.left, this.right);
155
156 Set<String> evaluate(environment) => right.evaluate(environment) ?
157 left.evaluate(environment) : new Set<String>();
158 String toString() => "($left if $right)";
159 }
160
161
162 class SetConstant implements SetExpression {
163 String value;
164
165 SetConstant(this.value);
166
167 Set<String> evaluate(environment) => new Set<String>.from([value]);
168 String toString() => value;
169 }
170
171
172 // An iterator that allows peeking at the current token.
173 class Scanner {
174 List<String> tokens;
175 Iterator tokenIterator;
176 String current;
177
178 Scanner(this.tokens) {
179 tokenIterator = tokens.iterator();
180 advance();
181 }
182
183 bool hasMore() => current != null;
184
185 void advance() {
186 current = tokenIterator.hasNext() ? tokenIterator.next() : null;
187 }
188 }
189
190
191 class ExpressionParser {
192 Scanner scanner;
193
194 ExpressionParser(this.scanner);
195
196 SetExpression parseSetExpression() => parseSetUnion();
197
198 SetExpression parseSetUnion() {
199 SetExpression left = parseSetIf();
200 while (scanner.hasMore() && scanner.current == Token.UNION){
201 scanner.advance();
202 SetExpression right = parseSetIf();
203 left = new SetUnion(left, right);
204 }
205 return left;
206 }
207
208 SetExpression parseSetIf() {
209 SetExpression left = parseSetOr();
210 while (scanner.hasMore() && scanner.current == "if") {
211 scanner.advance();
212 BooleanExpression right = parseBooleanExpression();
213 left = new SetIf(left, right);
214 }
215 return left;
216 }
217
218 SetExpression parseSetOr() {
219 SetExpression left = parseSetAtomic();
220 while (scanner.hasMore() && scanner.current == Token.OR){
221 scanner.advance();
222 SetExpression right = parseSetAtomic();
223 left = new SetUnion(left, right);
224 }
225 return left;
226 }
227
228
229 SetExpression parseSetAtomic() {
230 if (scanner.current == Token.LEFT_PAREN) {
231 scanner.advance();
232 SetExpression value = parseSetExpression();
233 Expect.equals(scanner.current, Token.RIGHT_PAREN,
234 "Missing right parenthesis in expression");
235 scanner.advance();
236 return value;
237 }
238 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
239 "Expected identifier in expression, got ${scanner.current}");
240 SetExpression value = new SetConstant(scanner.current);
241 scanner.advance();
242 return value;
243 }
244
245 BooleanExpression parseBooleanExpression() => parseBooleanOr();
246
247 BooleanExpression parseBooleanOr() {
248 BooleanExpression left = parseBooleanAnd();
249 while (scanner.hasMore() && scanner.current == Token.OR) {
250 scanner.advance();
251 BooleanExpression right = parseBooleanAnd();
252 left = new BooleanOperation(Token.OR, left, right);
253 }
254 return left;
255 }
256
257 BooleanExpression parseBooleanAnd() {
258 BooleanExpression left = parseBooleanAtomic();
259 while (scanner.hasMore() && scanner.current == Token.AND) {
260 scanner.advance();
261 BooleanExpression right = parseBooleanAtomic();
262 left = new BooleanOperation(Token.AND, left, right);
263 }
264 return left;
265 }
266
267 BooleanExpression parseBooleanAtomic() {
268 if (scanner.current == Token.LEFT_PAREN) {
269 scanner.advance();
270 SetExpression value = parseBooleanExpression();
271 Expect.equals(scanner.current, Token.RIGHT_PAREN,
272 "Missing right parenthesis in expression");
273 scanner.advance();
274 return value;
275 }
276
277 // The only atomic booleans are of the form $variable == value or the
278 // form $variable.
279 Expect.equals(scanner.current, Token.DOLLAR_SYMBOL,
280 "Expected \$ in expression, got ${scanner.current}");
281 scanner.advance();
282 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
283 "Expected identifier in expression, got ${scanner.current}");
284 TermVariable left = new TermVariable(scanner.current);
285 scanner.advance();
286 if (scanner.current == Token.EQUALS) {
287 scanner.advance();
288 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
289 "Expected identifier in expression, got ${scanner.current}");
290 TermConstant right = new TermConstant(scanner.current);
291 scanner.advance();
292 return new Comparison(left, right);
293 } else {
294 return new BooleanVariable(left);
295 }
296 }
297 }
298
OLDNEW
« no previous file with comments | « tests/standalone/src/StatusExpressionTest.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698