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

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: 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.
ngeoffray 2011/10/26 12:01:37 Extra space.
9 * There are set expressions and Boolean expressions in a .status file.
10 * The grammar is:
11 * BooleanExpression := $variable_name == value |
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 * Production are listed in order of precedence, and the || and , operators
Mads Ager (google) 2011/10/26 12:37:47 Remove the extra leading space starting from here
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 Tokenizer {
34 String expression;
35 List<String> tokens;
36
37 Tokenizer(String this.expression)
Søren Gjesse 2011/10/26 13:36:24 Fit on one line?
38 : tokens = new List<String>();
39
40 /**
41 * Tokens are : "&&", "||", "==", "$", "(", ")", ",", and (maximal) \w+.
Søren Gjesse 2011/10/26 13:36:24 Maybe list the tokens in the same order as they ar
42 */
43 static final test_regexp =
44 const RegExp(@"^([()$\w\s,]|(\&\&)|(\|\|)|(\=\=))+$");
45 static final regexp = const RegExp(@"[()$,]|(\&\&)|(\|\|)|(\=\=)|\w+");
46
47 void tokenize() {
48 if (!test_regexp.hasMatch(expression)) {
49 throw new ExpectException("Syntax error in '" + expression + '"');
50 }
51 for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
52 }
53 }
54
55
56 interface BooleanExpression {
57 bool evaluate(Map<String, String> environment);
58 }
59
60
61 interface SetExpression {
62 // A set of test outcomes.
Mads Ager (google) 2011/10/26 12:37:47 Please update the comment here to actually describ
63 Set<String> evaluate(Map<String, String> environment);
64 }
65
66
67 class Comparison implements BooleanExpression {
68 Variable left;
69 TermConstant right;
70
71 Comparison(this.left, this.right);
72
73 bool evaluate(environment) => left.termValue() == right.termValue();
74 String toString() => "==(\$${left.name}, ${right.value})";
Mads Ager (google) 2011/10/26 12:37:47 Why not just "(\$${left.name} == ${right.value})"?
75 }
76
77 class Variable {
78 String name;
79 Variable(String this.name);
80
81 String termValue(environment) => environment[name];
82 }
83
84 class TermConstant {
85 String value;
86 TermConstant(String this.value);
87
88 String termValue(environment) => value;
89 }
90
91
92 class BooleanOperation implements BooleanExpression {
93 String op;
94 BooleanExpression left;
95 BooleanExpression right;
96
97 BooleanOperation(this.op, this.left, this.right);
98
99 bool evaluate(environment) => (op == "&&") ?
100 left.evaluate(environment) && right.evaluate(environment) :
101 left.evaluate(environment) || right.evaluate(environment);
102 String toString() => "$op(${left.toString()},${right.toString()})";
Mads Ager (google) 2011/10/26 12:37:47 I would go for infix here and in the rest.
103 }
104
105 class SetUnion implements SetExpression {
106 SetExpression left;
107 SetExpression right;
108
109 SetUnion(this.left, this.right);
110
111 // Overwrites left.evaluate(env).
112 Set<String> evaluate(environment) =>
113 left.evaluate(environment).addAll(right.evaluate(environment));
114 String toString() => "||(${left.toString()},${right.toString()})";
115 }
116
117 class SetIf implements SetExpression {
118 SetExpression left;
119 BooleanExpression right;
120
121 SetIf(this.left, this.right);
122
123 Set<String> evaluate(environment) => right.evaluate(environment) ?
124 left.evaluate(environment) : new Set<String>();
125 String toString() => "if(${left.toString()},${right.toString()})";
126 }
127
128
129 class SetConstant implements SetExpression {
130 String value;
131
132 SetConstant(this.value);
133
134 Set<String> evaluate(environment) => new Set<string>().add(value);
135 String toString() => value;
136 }
137
138
139 /* An iterator that provides peeking at the current token. */
Mads Ager (google) 2011/10/26 12:37:47 I think you should either make this a doc comment
William Hesse 2011/10/26 15:15:03 Done.
140 class Scanner {
Søren Gjesse 2011/10/26 13:36:24 Should we have token constants? class Token { f
William Hesse 2011/10/26 15:15:03 Done.
141 List<String> tokens;
142 Iterator token_iterator;
143 String current;
144
145 Scanner(this.tokens) {
146 //print(tokens[0] + tokens[1]);
Mads Ager (google) 2011/10/26 12:37:47 remove.
William Hesse 2011/10/26 15:15:03 Done.
147 token_iterator = tokens.iterator();
148 current = token_iterator.next();
Mads Ager (google) 2011/10/26 12:37:47 Shouldn't this just call advance?
William Hesse 2011/10/26 15:15:03 Done.
149 //print(current);
Mads Ager (google) 2011/10/26 12:37:47 remove.
William Hesse 2011/10/26 15:15:03 Done.
150 }
151
152 bool hasMore() => current != null;
153
154 void advance() {
155 current = token_iterator.hasNext() ? token_iterator.next() : null;
156 print(current);
Mads Ager (google) 2011/10/26 12:37:47 remove
William Hesse 2011/10/26 15:15:03 Done.
157 }
158 }
159
160 class ExpressionParser {
161 Scanner scanner;
Søren Gjesse 2011/10/26 13:36:24 Empty line before the constructor.
William Hesse 2011/10/26 15:15:03 Done.
162 ExpressionParser(this.scanner);
163
164 SetExpression parseSetExpression() => parseSetUnion();
165
166 SetExpression parseSetUnion() {
167 SetExpression left = parseSetIf();
168 while (scanner.hasMore() && scanner.current == ","){
169 scanner.advance();
170 SetExpression right = parseSetIf();
171 left = new SetUnion(left, right);
172 }
173 return left;
174 }
175
176 SetExpression parseSetIf() {
177 SetExpression left = parseSetOr();
178 while (scanner.hasMore() && scanner.current == "if") {
179 scanner.advance();
180 BooleanExpression right = parseBooleanExpression();
181 left = new SetIf(left, right);
182 }
183 return left;
184 }
185
186 SetExpression parseSetOr() {
187 SetExpression left = parseSetAtomic();
188 while (scanner.hasMore() && scanner.current == "||"){
189 scanner.advance();
190 SetExpression right = parseSetIf();
191 left = new SetUnion(left, right);
192 }
193 return left;
194 }
195
196
197 SetExpression parseSetAtomic() {
198 if (scanner.current == "(") {
199 scanner.advance();
200 SetExpression value = parseSetUnion();
201 Expect.equals(scanner.current, ")",
202 "Missing right parenthesis in expression");
Mads Ager (google) 2011/10/26 12:37:47 Please align with first parameter.
William Hesse 2011/10/26 15:15:03 Done.
203 scanner.advance();
204 return value;
205 }
206 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
207 "Expected identifier in expression, got " + scanner.current);
Mads Ager (google) 2011/10/26 12:37:47 Please align with first parameter or move both to
William Hesse 2011/10/26 15:15:03 Done.
208 SetExpression value = new SetConstant(scanner.current);
209 scanner.advance();
210 return value;
211 }
212
213 BooleanExpression parseBooleanExpression() => parseBooleanOr();
214
215 BooleanExpression parseBooleanOr() {
216 BooleanExpression left = parseBooleanAnd();
217 while (scanner.hasMore() && scanner.current == "||") {
218 scanner.advance();
219 BooleanExpression right = parseBooleanAnd();
220 left = new BooleanOperation("||", left, right);
221 }
222 return left;
223 }
224
225
226 BooleanExpression parseBooleanAnd() {
227 BooleanExpression left = parseBooleanAtomic();
228 while (scanner.hasMore() && scanner.current == "&&") {
229 scanner.advance();
230 BooleanExpression right = parseBooleanAtomic();
231 left = new BooleanOperation("&&", left, right);
232 }
233 return left;
234 }
235
236 BooleanExpression parseBooleanAtomic() {
237 if (scanner.current == "(") {
238 scanner.advance();
239 SetExpression value = parseBooleanExpression();
240 Expect.equals(scanner.current, ")",
241 "Missing right parenthesis in expression");
Mads Ager (google) 2011/10/26 12:37:47 align
William Hesse 2011/10/26 15:15:03 Done.
242 scanner.advance();
243 return value;
244 }
245
246 // The only atomic booleans are of the form $variable == value.
247 Expect.equals(scanner.current, @"$",
248 @"Expected $identifier in expression, got " + scanner.current);
Mads Ager (google) 2011/10/26 12:37:47 $identifier -> $
William Hesse 2011/10/26 15:15:03 Done.
249 scanner.advance();
250 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
251 @"Expected $identifier in expression, got " + scanner.current);
252 Variable left = new Variable(scanner.current);
253 scanner.advance();
254 Expect.equals(scanner.current, "==",
255 "Expected == in expression, got " + scanner.current);
256 scanner.advance();
257 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current),
258 @"Expected identifier in expression, got " + scanner.current);
Søren Gjesse 2011/10/26 13:36:24 No need for @ here.
William Hesse 2011/10/26 15:15:03 Done.
259 TermConstant right = new TermConstant(scanner.current);
260 scanner.advance();
261 return new Comparison(left, right);
262 }
263 }
264
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