OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'environment.dart'; | 5 import '../environment.dart'; |
6 | 6 |
7 /// A parsed Boolean expression AST. | 7 /// A parsed Boolean expression AST. |
8 abstract class Expression { | 8 abstract class Expression { |
9 /// Parses Boolean expressions in a .status file for Dart. | 9 /// Parses Boolean expressions in a .status file for Dart. |
10 /// | 10 /// |
11 /// The grammar is: | 11 /// The grammar is: |
12 /// | 12 /// |
13 /// expression := or | 13 /// expression := or |
14 /// or := and ( "||" and )* | 14 /// or := and ( "||" and )* |
15 /// and := primary ( "&&" primary )* | 15 /// and := primary ( "&&" primary )* |
16 /// primary := "$" identifier ( "==" | "!=" ) identifier | | 16 /// primary := "$" identifier ( "==" | "!=" ) identifier | |
17 /// "!"? "$" identifier | | 17 /// "!"? "$" identifier | |
18 /// "(" expression ")" | 18 /// "(" expression ")" |
19 /// identifier := regex "\w+" | 19 /// identifier := regex "\w+" |
20 /// | 20 /// |
21 /// Expressions evaluate as expected, with values of variables found in an | 21 /// Expressions evaluate as expected, with values of variables found in an |
22 /// environment passed to the evaluator. | 22 /// environment passed to the evaluator. |
23 static Expression parse(String expression) => | 23 static Expression parse(String expression) => |
24 new _ExpressionParser(expression).parse(); | 24 new _ExpressionParser(expression).parse(); |
25 | 25 |
26 /// Validates that this expression does not contain any invalid uses of | 26 /// Validates that this expression does not contain any invalid uses of |
27 /// variables. | 27 /// variables. |
28 /// | 28 /// |
29 /// Ensures that any variable names are known and that any literal values are | 29 /// Ensures that any variable names are known and that any literal values are |
30 /// allowed for their corresponding variable. If an invalid variable or value | 30 /// allowed for their corresponding variable. If an invalid variable or value |
31 /// is found, adds appropriate error messages to [errors]. | 31 /// is found, adds appropriate error messages to [errors]. |
32 void validate(List<String> errors); | 32 void validate(Environment environment, List<String> errors); |
33 | 33 |
34 /// Evaluates the expression where all variables are defined by the given | 34 /// Evaluates the expression where all variables are defined by the given |
35 /// [environment]. | 35 /// [environment]. |
36 bool evaluate(Environment environment); | 36 bool evaluate(Environment environment); |
37 } | 37 } |
38 | 38 |
39 /// Keyword token strings. | 39 /// Keyword token strings. |
40 class _Token { | 40 class _Token { |
41 static const leftParen = "("; | 41 static const leftParen = "("; |
42 static const rightParen = ")"; | 42 static const rightParen = ")"; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 /// $variable == someValue | 76 /// $variable == someValue |
77 /// ``` | 77 /// ``` |
78 /// Negate the result if [negate] is true. | 78 /// Negate the result if [negate] is true. |
79 class _ComparisonExpression implements Expression { | 79 class _ComparisonExpression implements Expression { |
80 final _Variable left; | 80 final _Variable left; |
81 final String right; | 81 final String right; |
82 final bool negate; | 82 final bool negate; |
83 | 83 |
84 _ComparisonExpression(this.left, this.right, this.negate); | 84 _ComparisonExpression(this.left, this.right, this.negate); |
85 | 85 |
86 void validate(List<String> errors) { | 86 void validate(Environment environment, List<String> errors) { |
87 Environment.validate(left.name, right, errors); | 87 environment.validate(left.name, right, errors); |
88 } | 88 } |
89 | 89 |
90 bool evaluate(Environment environment) { | 90 bool evaluate(Environment environment) { |
91 return negate != (left.lookup(environment) == right); | 91 return negate != (left.lookup(environment) == right); |
92 } | 92 } |
93 | 93 |
94 String toString() => "(\$${left.name} ${negate ? '!=' : '=='} $right)"; | 94 String toString() => "(\$${left.name} ${negate ? '!=' : '=='} $right)"; |
95 } | 95 } |
96 | 96 |
97 /// A reference to a variable defined in the environment. The expression | 97 /// A reference to a variable defined in the environment. The expression |
(...skipping 12 matching lines...) Expand all Loading... |
110 /// is equivalent to | 110 /// is equivalent to |
111 /// ``` | 111 /// ``` |
112 /// $variable != true | 112 /// $variable != true |
113 /// ``` | 113 /// ``` |
114 class _VariableExpression implements Expression { | 114 class _VariableExpression implements Expression { |
115 final _Variable variable; | 115 final _Variable variable; |
116 final bool negate; | 116 final bool negate; |
117 | 117 |
118 _VariableExpression(this.variable, {this.negate = false}); | 118 _VariableExpression(this.variable, {this.negate = false}); |
119 | 119 |
120 void validate(List<String> errors) { | 120 void validate(Environment environment, List<String> errors) { |
121 // It must be a Boolean, so it should allow either Boolean value. | 121 // It must be a Boolean, so it should allow either Boolean value. |
122 Environment.validate(variable.name, "true", errors); | 122 environment.validate(variable.name, "true", errors); |
123 } | 123 } |
124 | 124 |
125 bool evaluate(Environment environment) => | 125 bool evaluate(Environment environment) => |
126 negate != (variable.lookup(environment) == "true"); | 126 negate != (variable.lookup(environment) == "true"); |
127 | 127 |
128 String toString() => "(bool ${negate ? "! " : ""}\$${variable.name})"; | 128 String toString() => "(bool ${negate ? "! " : ""}\$${variable.name})"; |
129 } | 129 } |
130 | 130 |
131 /// A logical `||` or `&&` expression. | 131 /// A logical `||` or `&&` expression. |
132 class _LogicExpression implements Expression { | 132 class _LogicExpression implements Expression { |
133 /// The operator, `||` or `&&`. | 133 /// The operator, `||` or `&&`. |
134 final String op; | 134 final String op; |
135 | 135 |
136 final Expression left; | 136 final Expression left; |
137 final Expression right; | 137 final Expression right; |
138 | 138 |
139 _LogicExpression(this.op, this.left, this.right); | 139 _LogicExpression(this.op, this.left, this.right); |
140 | 140 |
141 void validate(List<String> errors) { | 141 void validate(Environment environment, List<String> errors) { |
142 left.validate(errors); | 142 left.validate(environment, errors); |
143 right.validate(errors); | 143 right.validate(environment, errors); |
144 } | 144 } |
145 | 145 |
146 bool evaluate(Environment environment) => (op == _Token.and) | 146 bool evaluate(Environment environment) => (op == _Token.and) |
147 ? left.evaluate(environment) && right.evaluate(environment) | 147 ? left.evaluate(environment) && right.evaluate(environment) |
148 : left.evaluate(environment) || right.evaluate(environment); | 148 : left.evaluate(environment) || right.evaluate(environment); |
149 | 149 |
150 String toString() => "($left $op $right)"; | 150 String toString() => "($left $op $right)"; |
151 } | 151 } |
152 | 152 |
153 /// Parser for Boolean expressions in a .status file for Dart. | 153 /// Parser for Boolean expressions in a .status file for Dart. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 return true; | 283 return true; |
284 } | 284 } |
285 | 285 |
286 /// Consumes the current token and returns it. | 286 /// Consumes the current token and returns it. |
287 String advance() { | 287 String advance() { |
288 var previous = current; | 288 var previous = current; |
289 current = tokenIterator.moveNext() ? tokenIterator.current : null; | 289 current = tokenIterator.moveNext() ? tokenIterator.current : null; |
290 return previous; | 290 return previous; |
291 } | 291 } |
292 } | 292 } |
OLD | NEW |