Chromium Code Reviews| Index: frog/tests/leg_only/src/CascadePrecedenceTest.dart |
| diff --git a/frog/tests/leg_only/src/CascadePrecedenceTest.dart b/frog/tests/leg_only/src/CascadePrecedenceTest.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2ed263e0e4a291c6578e1a055e6ce1c7af3b5462 |
| --- /dev/null |
| +++ b/frog/tests/leg_only/src/CascadePrecedenceTest.dart |
| @@ -0,0 +1,137 @@ |
| +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| + |
| +class A { |
| + int value; |
| + A(this.value); |
| + void set(int value) { this.value = value; } |
| + int get() => value; |
| + int operator[](int index) => value + index; |
| + void operator[]=(int index, int newValue) { value += -index + newValue; } |
| + void test(int expected) { |
| + Expect.equals(expected, value); |
| + } |
| + Function limp(int n) { |
| + if (n == 0) return set; |
| + return () => limp(n - 1); |
| + } |
| + A get self() => this; |
| + A operator+(A other) { |
| + this.value += other.value; |
| + return this; |
| + } |
| +} |
| + |
| +class Box { |
| + A value; |
| + Box(this.value); |
| + A operator[](int pos) => value; |
| + void operator[]=(int pos, A a) { value = a; } |
| + A get x() => value; |
| + void set x(A a) { value = a; } |
| +} |
| + |
| +// Subset of grammar being tested. |
| +// |
| +// expression: |
| +// assignableExpression assignmentOperator expression |
| +// | conditionalExpression cascadeSection* |
| +// ; |
| +// expressionWithoutCascade: |
| +// assignableExpression assignmentOperator expressionWithoutCascade |
| +// | conditionalExpression |
| +// ; |
| +// expressionList: |
| +// expression (',' expression)* |
| +// ; |
| +// assignableExpression: |
| +// primary (arguments* assignableSelector)+ |
| +// | super assignableSelector |
| +// | identifier |
| +// ; |
| +// conditionalExpression: |
| +// logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)? |
|
ahe
2012/05/01 15:50:50
Long line.
|
| +// ; |
| +// primary: |
| +// thisExpression |
| +// | super assignableSelector |
| +// | functionExpression |
| +// | literal |
| +// | identifier |
| +// | newExpression |
| +// | constObjectExpression |
| +// | '(' expression ')' |
| +// ; |
| +// assignableSelector: |
| +// '[' expression ']' |
| +// | '.' identifier |
| +// ; |
| +// |
| +// In words: |
| +// An assignableExpression is either a variable or something ending in |
| +// [expression] or .identifier. |
| + |
| +main() { |
| + A a = new A(42); |
| + A original = a; |
| + A b = new A(87); |
| + fa() => a; |
| + Box box = new Box(a); |
| + // Different expressions on the left-hand side of '..'. |
| + // conditionalExpression >> postfixExpression > primary selector* |
| + Expect.equals(a, a..set(37)..get()); |
| + a.test(37); |
| + Expect.equals(a, fa()..set(42)..get()); |
| + a.test(42); |
| + Expect.equals(a, box.x..set(37)..get()); |
| + a.test(37); |
| + // '..' binds to 'b + a', i.e., to the 'b' object, not to 'a'. |
| + Expect.equals(b, b + a..test(124)..set(117)..get()); |
| + b.test(117); |
| + a.test(37); |
| + |
| + // expression :: conditionalExpression cascadeSection |
| + // and conditionalExpression ends in expressionWithoutCascade. |
| + // I.e., '..' binds to the entire condition expression, not to 'b'. |
| + (a.value == 37) ? a : b..set(42); |
| + a.test(42); |
| + |
| + // This binds .. to 'a', not 'c=a', and performs assignment after reading |
| + // c.get(). |
| + A c = new A(21); |
| + c = a..set(c.get()); // FAILING. |
| + Expect.equals(a, c); |
| + Expect.equals(original, a); |
| + a.test(21); // Fails as 42 if above is parsed as (c = a)..set(c.get()). |
| + |
| + // Should be parsed as (box..x = (c = a))..x.test(21). |
| + c = null; |
| + box..x = c = a..x.test(21); |
| + c.test(21); |
| + // Other variants |
| + c = null; |
| + box..x = c = (a..test(21))..x.test(21); |
| + c.test(21); |
| + |
| + c = null; |
| + box..x = (c = a..test(21))..x.test(21); |
| + c.test(21); |
| + |
| + // Should work the same: |
| + (a..set(42))..test(42); |
| + a..set(21)..test(21); |
| + |
| + c = null; |
| + Box originalBox = box; |
| + // Should parse as: |
| + // box = (box..x = (a.value == 21 ? b : c)..x.test(117)); |
| + box = box..x = a.value == 21 ? b : c..x.test(117); |
| + Expect.equals(originalBox, box); |
| + Expect.equals(box.value, b); |
| + |
| + // New cascades are allowed inside an expressionWithoutCascade if properly |
| + // delimited. |
| + box..x = (a..set(42)..test(42))..x.test(42); |
| +} |