| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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("status_expression"); | 5 #library("status_expression"); |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Parse and evaluate expressions in a .status file for Dart and V8. | 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. | 9 * There are set expressions and Boolean expressions in a .status file. |
| 10 * The grammar is: | 10 * The grammar is: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 * Values and variableNames are non-empty strings of word characters, matching | 24 * Values and variableNames are non-empty strings of word characters, matching |
| 25 * the RegExp \w+. | 25 * the RegExp \w+. |
| 26 * | 26 * |
| 27 * Expressions evaluate as expected, with values of variables found in | 27 * Expressions evaluate as expected, with values of variables found in |
| 28 * an environment passed to the evaluator. The SetExpression "value" | 28 * an environment passed to the evaluator. The SetExpression "value" |
| 29 * evaluates to a singleton set containing that value. "A if B" evaluates | 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. | 30 * to A if B is true, and to the empty set if B is false. |
| 31 */ | 31 */ |
| 32 | 32 |
| 33 | 33 |
| 34 class Token | 34 class Token |
| 35 { | 35 { |
| 36 static final String LEFT_PAREN = "("; | 36 static const String LEFT_PAREN = "("; |
| 37 static final String RIGHT_PAREN = ")"; | 37 static const String RIGHT_PAREN = ")"; |
| 38 static final String DOLLAR_SYMBOL = @"$"; | 38 static const String DOLLAR_SYMBOL = r"$"; |
| 39 static final String UNION = ","; | 39 static const String UNION = ","; |
| 40 static final String EQUALS = "=="; | 40 static const String EQUALS = "=="; |
| 41 static final String AND = "&&"; | 41 static const String AND = "&&"; |
| 42 static final String OR = "||"; | 42 static const String OR = "||"; |
| 43 } | 43 } |
| 44 | 44 |
| 45 | 45 |
| 46 class Tokenizer { | 46 class Tokenizer { |
| 47 String expression; | 47 String expression; |
| 48 List<String> tokens; | 48 List<String> tokens; |
| 49 | 49 |
| 50 Tokenizer(String this.expression) | 50 Tokenizer(String this.expression) |
| 51 : tokens = new List<String>(); | 51 : tokens = new List<String>(); |
| 52 | 52 |
| 53 // Tokens are : "(", ")", "$", ",", "&&", "||", "==", and (maximal) \w+. | 53 // Tokens are : "(", ")", "$", ",", "&&", "||", "==", and (maximal) \w+. |
| 54 static final testRegexp = | 54 static const testRegexp = |
| 55 const RegExp(@"^([()$\w\s,]|(\&\&)|(\|\|)|(\=\=))+$"); | 55 const RegExp(r"^([()$\w\s,]|(\&\&)|(\|\|)|(\=\=))+$"); |
| 56 static final regexp = const RegExp(@"[()$,]|(\&\&)|(\|\|)|(\=\=)|\w+"); | 56 static const regexp = const RegExp(r"[()$,]|(\&\&)|(\|\|)|(\=\=)|\w+"); |
| 57 | 57 |
| 58 List<String> tokenize() { | 58 List<String> tokenize() { |
| 59 if (!testRegexp.hasMatch(expression)) { | 59 if (!testRegexp.hasMatch(expression)) { |
| 60 throw new ExpectException("Syntax error in '$expression'"); | 60 throw new ExpectException("Syntax error in '$expression'"); |
| 61 } | 61 } |
| 62 for (Match match in regexp.allMatches(expression)) tokens.add(match[0]); | 62 for (Match match in regexp.allMatches(expression)) tokens.add(match[0]); |
| 63 return tokens; | 63 return tokens; |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 | 66 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 class SetIf implements SetExpression { | 150 class SetIf implements SetExpression { |
| 151 SetExpression left; | 151 SetExpression left; |
| 152 BooleanExpression right; | 152 BooleanExpression right; |
| 153 | 153 |
| 154 SetIf(this.left, this.right); | 154 SetIf(this.left, this.right); |
| 155 | 155 |
| 156 Set<String> evaluate(environment) => right.evaluate(environment) ? | 156 Set<String> evaluate(environment) => right.evaluate(environment) ? |
| 157 left.evaluate(environment) : new Set<String>(); | 157 left.evaluate(environment) : new Set<String>(); |
| 158 String toString() => "($left if $right)"; | 158 String toString() => "($left if $right)"; |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 class SetConstant implements SetExpression { | 162 class SetConstant implements SetExpression { |
| 163 String value; | 163 String value; |
| 164 | 164 |
| 165 SetConstant(String v) : value = v.toLowerCase(); | 165 SetConstant(String v) : value = v.toLowerCase(); |
| 166 | 166 |
| 167 Set<String> evaluate(environment) => new Set<String>.from([value]); | 167 Set<String> evaluate(environment) => new Set<String>.from([value]); |
| 168 String toString() => value; | 168 String toString() => value; |
| 169 } | 169 } |
| 170 | 170 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 | 228 |
| 229 SetExpression parseSetAtomic() { | 229 SetExpression parseSetAtomic() { |
| 230 if (scanner.current == Token.LEFT_PAREN) { | 230 if (scanner.current == Token.LEFT_PAREN) { |
| 231 scanner.advance(); | 231 scanner.advance(); |
| 232 SetExpression value = parseSetExpression(); | 232 SetExpression value = parseSetExpression(); |
| 233 Expect.equals(scanner.current, Token.RIGHT_PAREN, | 233 Expect.equals(scanner.current, Token.RIGHT_PAREN, |
| 234 "Missing right parenthesis in expression"); | 234 "Missing right parenthesis in expression"); |
| 235 scanner.advance(); | 235 scanner.advance(); |
| 236 return value; | 236 return value; |
| 237 } | 237 } |
| 238 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current), | 238 Expect.isTrue(const RegExp(r"^\w+$").hasMatch(scanner.current), |
| 239 "Expected identifier in expression, got ${scanner.current}"); | 239 "Expected identifier in expression, got ${scanner.current}"); |
| 240 SetExpression value = new SetConstant(scanner.current); | 240 SetExpression value = new SetConstant(scanner.current); |
| 241 scanner.advance(); | 241 scanner.advance(); |
| 242 return value; | 242 return value; |
| 243 } | 243 } |
| 244 | 244 |
| 245 BooleanExpression parseBooleanExpression() => parseBooleanOr(); | 245 BooleanExpression parseBooleanExpression() => parseBooleanOr(); |
| 246 | 246 |
| 247 BooleanExpression parseBooleanOr() { | 247 BooleanExpression parseBooleanOr() { |
| 248 BooleanExpression left = parseBooleanAnd(); | 248 BooleanExpression left = parseBooleanAnd(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 272 "Missing right parenthesis in expression"); | 272 "Missing right parenthesis in expression"); |
| 273 scanner.advance(); | 273 scanner.advance(); |
| 274 return value; | 274 return value; |
| 275 } | 275 } |
| 276 | 276 |
| 277 // The only atomic booleans are of the form $variable == value or the | 277 // The only atomic booleans are of the form $variable == value or the |
| 278 // form $variable. | 278 // form $variable. |
| 279 Expect.equals(scanner.current, Token.DOLLAR_SYMBOL, | 279 Expect.equals(scanner.current, Token.DOLLAR_SYMBOL, |
| 280 "Expected \$ in expression, got ${scanner.current}"); | 280 "Expected \$ in expression, got ${scanner.current}"); |
| 281 scanner.advance(); | 281 scanner.advance(); |
| 282 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current), | 282 Expect.isTrue(const RegExp(r"^\w+$").hasMatch(scanner.current), |
| 283 "Expected identifier in expression, got ${scanner.current}"); | 283 "Expected identifier in expression, got ${scanner.current}"); |
| 284 TermVariable left = new TermVariable(scanner.current); | 284 TermVariable left = new TermVariable(scanner.current); |
| 285 scanner.advance(); | 285 scanner.advance(); |
| 286 if (scanner.current == Token.EQUALS) { | 286 if (scanner.current == Token.EQUALS) { |
| 287 scanner.advance(); | 287 scanner.advance(); |
| 288 Expect.isTrue(const RegExp(@"^\w+$").hasMatch(scanner.current), | 288 Expect.isTrue(const RegExp(r"^\w+$").hasMatch(scanner.current), |
| 289 "Expected identifier in expression, got ${scanner.current}"); | 289 "Expected identifier in expression, got ${scanner.current}"); |
| 290 TermConstant right = new TermConstant(scanner.current); | 290 TermConstant right = new TermConstant(scanner.current); |
| 291 scanner.advance(); | 291 scanner.advance(); |
| 292 return new Comparison(left, right); | 292 return new Comparison(left, right); |
| 293 } else { | 293 } else { |
| 294 return new BooleanVariable(left); | 294 return new BooleanVariable(left); |
| 295 } | 295 } |
| 296 } | 296 } |
| 297 } | 297 } |
| 298 | 298 |
| OLD | NEW |