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

Side by Side Diff: tools/testing/dart/status_expressions_lib.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: Addressed comments, added and tested boolean variables. 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
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_expressions");
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 := $variable_name == value |
kasperl 2011/10/27 10:43:31 camelCase
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 names 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 Token {
34 static final String AND = "&&";
35 static final String OR = "||";
36 static final String UNION = ",";
37 }
38
39 class Tokenizer {
40 String expression;
41 List<String> tokens;
42
43 Tokenizer(String this.expression)
44 : tokens = new List<String>();
45
46 // Tokens are : "(", ")", "$", ",", "&&", "||", "==", and (maximal) \w+.
47 static final testRegexp =
48 const RegExp(@"^([()$\w\s,]|(\&\&)|(\|\|)|(\=\=))+$");
49 static final regexp = const RegExp(@"[()$,]|(\&\&)|(\|\|)|(\=\=)|\w+");
50
51 void tokenize() {
52 if (!testRegexp.hasMatch(expression)) {
53 throw new ExpectException("Syntax error in '$expression'");
54 }
55 for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
56 }
57 }
58
59
60 interface BooleanExpression {
61 bool evaluate(Map<String, String> environment);
62 }
63
64
65 interface SetExpression {
66 Set<String> evaluate(Map<String, String> environment);
67 }
68
69
70 class Comparison implements BooleanExpression {
71 Variable left;
72 TermConstant right;
73
74 Comparison(this.left, this.right);
75
76 bool evaluate(environment) => left.termValue() == right.termValue();
77 String toString() => "(\$${left.name} == ${right.value})";
78 }
79
Mads Ager (google) 2011/10/27 07:07:47 Two blank lines?
80 class Variable {
81 String name;
82
83 Variable(this.name);
84
85 String termValue(environment) => environment[name];
86 }
87
Mads Ager (google) 2011/10/27 07:07:47 Two blank lines?
88 class TermConstant {
Mads Ager (google) 2011/10/27 07:07:47 Should this just be named Constant or should Varia
89 String value;
90
91 TermConstant(String this.value);
92
93 String termValue(environment) => value;
94 }
95
96
97 class BooleanVariable implements BooleanExpression {
98 Variable variable;
99
100 BooleanVariable(this.variable);
101
102 bool evaluate(environment) => variable.termValue(environment) == "true";
103 String toString() => "(bool \$${variable.name})";
104 }
105
106
107 class BooleanOperation implements BooleanExpression {
108 String op;
109 BooleanExpression left;
110 BooleanExpression right;
111
112 BooleanOperation(this.op, this.left, this.right);
113
114 bool evaluate(environment) => (op == Token.AND) ?
115 left.evaluate(environment) && right.evaluate(environment) :
116 left.evaluate(environment) || right.evaluate(environment);
117 String toString() => "($left $op $right)";
118 }
119
120 class SetUnion implements SetExpression {
121 SetExpression left;
122 SetExpression right;
123
124 SetUnion(this.left, this.right);
125
126 // Overwrites left.evaluate(env).
127 Set<String> evaluate(environment) =>
128 left.evaluate(environment).addAll(right.evaluate(environment));
129 String toString() => "($left || $right)";
130 }
131
132 class SetIf implements SetExpression {
133 SetExpression left;
134 BooleanExpression right;
135
136 SetIf(this.left, this.right);
137
138 Set<String> evaluate(environment) => right.evaluate(environment) ?
139 left.evaluate(environment) : new Set<String>();
140 String toString() => "($left if $right)";
141 }
142
143
144 class SetConstant implements SetExpression {
145 String value;
146
147 SetConstant(this.value);
148
149 Set<String> evaluate(environment) => new Set<string>().add(value);
150 String toString() => value;
151 }
152
153
154 // An iterator that allows peeking at the current token.
155 class Scanner {
156 List<String> tokens;
157 Iterator token_iterator;
kasperl 2011/10/27 10:43:31 camelCase
158 String current;
159
160 Scanner(this.tokens) {
161 token_iterator = tokens.iterator();
162 advance();
163 }
164
165 bool hasMore() => current != null;
166
167 void advance() {
168 current = token_iterator.hasNext() ? token_iterator.next() : null;
169 }
170 }
171
172 class ExpressionParser {
173 Scanner scanner;
174
175 ExpressionParser(this.scanner);
176
177 SetExpression parseSetExpression() => parseSetUnion();
178
179 SetExpression parseSetUnion() {
180 SetExpression left = parseSetIf();
181 while (scanner.hasMore() && scanner.current == Token.UNION){
182 scanner.advance();
183 SetExpression right = parseSetIf();
184 left = new SetUnion(left, right);
185 }
186 return left;
187 }
188
189 SetExpression parseSetIf() {
190 SetExpression left = parseSetOr();
191 while (scanner.hasMore() && scanner.current == "if") {
192 scanner.advance();
193 BooleanExpression right = parseBooleanExpression();
194 left = new SetIf(left, right);
195 }
196 return left;
197 }
198
199 SetExpression parseSetOr() {
200 SetExpression left = parseSetAtomic();
201 while (scanner.hasMore() && scanner.current == Token.OR){
202 scanner.advance();
203 SetExpression right = parseSetAtomic();
204 left = new SetUnion(left, right);
205 }
206 return left;
207 }
208
209
210 SetExpression parseSetAtomic() {
211 if (scanner.current == "(") {
Søren Gjesse 2011/10/27 10:22:20 Token for (.
212 scanner.advance();
213 SetExpression value = parseSetExpression();
214 Expect.equals(scanner.current, ")",
Søren Gjesse 2011/10/27 10:22:20 and ).
215 "Missing right parenthesis in expression");
216 scanner.advance();
217 return value;
218 }
219 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
220 "Expected identifier in expression, got ${scanner.current}");
221 SetExpression value = new SetConstant(scanner.current);
222 scanner.advance();
223 return value;
224 }
225
226 BooleanExpression parseBooleanExpression() => parseBooleanOr();
227
228 BooleanExpression parseBooleanOr() {
229 BooleanExpression left = parseBooleanAnd();
230 while (scanner.hasMore() && scanner.current == Token.OR) {
231 scanner.advance();
232 BooleanExpression right = parseBooleanAnd();
233 left = new BooleanOperation(Token.OR, left, right);
234 }
235 return left;
236 }
237
238
239 BooleanExpression parseBooleanAnd() {
240 BooleanExpression left = parseBooleanAtomic();
241 while (scanner.hasMore() && scanner.current == Token.AND) {
242 scanner.advance();
243 BooleanExpression right = parseBooleanAtomic();
244 left = new BooleanOperation(Token.AND, left, right);
245 }
246 return left;
247 }
248
249 BooleanExpression parseBooleanAtomic() {
250 if (scanner.current == "(") {
251 scanner.advance();
252 SetExpression value = parseBooleanExpression();
253 Expect.equals(scanner.current, ")",
254 "Missing right parenthesis in expression");
255 scanner.advance();
256 return value;
257 }
258
259 // The only atomic booleans are of the form $variable == value or the
260 // form $variable.
261 Expect.equals(scanner.current, @"$",
262 "Expected \$ in expression, got ${scanner.current}");
263 scanner.advance();
264 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
265 "Expected identifier in expression, got ${scanner.current}");
266 Variable left = new Variable(scanner.current);
267 scanner.advance();
268 if (scanner.current == "==") {
Søren Gjesse 2011/10/27 10:22:20 Token for ==
269 scanner.advance();
270 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
271 "Expected identifier in expression, got ${scanner.current}");
272 TermConstant right = new TermConstant(scanner.current);
273 scanner.advance();
274 return new Comparison(left, right);
275 } else {
276 return new BooleanVariable(left);
277 }
278 }
279 }
280
OLDNEW
« no previous file with comments | « no previous file | tools/testing/dart/test_status_expressions.dart » ('j') | tools/testing/dart/test_status_expressions.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698