aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/DictComprehension.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Parser.java60
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java8
3 files changed, 43 insertions, 26 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DictComprehension.java b/src/main/java/com/google/devtools/build/lib/syntax/DictComprehension.java
index e3f813ca45..3687be7dcf 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/DictComprehension.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/DictComprehension.java
@@ -21,6 +21,7 @@ import java.util.LinkedHashMap;
* Syntax node for dictionary comprehension expressions.
*/
public class DictComprehension extends Expression {
+ // TODO(bazel-team): Factor code with ListComprehension.java.
private final Expression keyExpression;
private final Expression valueExpression;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index e993821dd8..e25ca98b4e 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -777,6 +777,39 @@ class Parser {
return setLocation(ListLiteral.makeTuple(tuple), start, token.right);
}
+ // comprehension_suffix ::= 'FOR' loop_variables 'IN' expr comprehension_suffix
+ // | 'IF' expr comprehension_suffix
+ // | ']'
+ private Expression parseComprehensionSuffix(ListComprehension listComprehension) {
+ while (true) {
+ switch (token.kind) {
+ case FOR:
+ nextToken();
+ Expression loopVar = parseForLoopVariables();
+ expect(TokenKind.IN);
+ Expression listExpression = parseExpression();
+ listComprehension.add(loopVar, listExpression);
+ break;
+
+ case IF:
+ reportError(lexer.createLocation(token.left, token.right),
+ "List comprehension with filtering is not yet supported");
+ nextToken();
+ parseExpression(); // condition
+ break;
+
+ case RBRACKET:
+ nextToken();
+ return listComprehension;
+
+ default:
+ syntaxError(token, "expected ']', 'for' or 'if'");
+ syncPast(LIST_TERMINATOR_SET);
+ return makeErrorExpression(token.left, token.right);
+ }
+ }
+ }
+
// list_maker ::= '[' ']'
// |'[' expr ']'
// |'[' expr expr_list ']'
@@ -801,28 +834,8 @@ class Parser {
return literal;
}
case FOR: { // list comprehension
- ListComprehension listComprehension =
- new ListComprehension(expression);
- do {
- nextToken();
- Expression loopVar = parseForLoopVariables();
- if (token.kind == TokenKind.IN) {
- nextToken();
- Expression listExpression = parseExpression();
- listComprehension.add(loopVar, listExpression);
- } else {
- break;
- }
- if (token.kind == TokenKind.RBRACKET) {
- setLocation(listComprehension, start, token.right);
- nextToken();
- return listComprehension;
- }
- } while (token.kind == TokenKind.FOR);
-
- syntaxError(token, "expected 'for' or ']'");
- int end = syncPast(LIST_TERMINATOR_SET);
- return makeErrorExpression(start, end);
+ Expression result = parseComprehensionSuffix(new ListComprehension(expression));
+ return setLocation(result, start, token.right);
}
case COMMA: {
List<Expression> list = parseExprList();
@@ -861,6 +874,9 @@ class Parser {
}
DictionaryEntryLiteral entry = parseDictEntry();
if (token.kind == TokenKind.FOR) {
+ // TODO(bazel-team): Reuse parseComprehensionSuffix when dict
+ // comprehension is compatible with list comprehension.
+
// Dict comprehension
nextToken();
Expression loopVar = parseForLoopVariables();
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
index e568fd12a9..5f7deb7dc9 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
@@ -273,7 +273,7 @@ public class ParserTest extends EvaluationTestCase {
public void testErrorRecovery() throws Exception {
setFailFast(false);
- String expr = "f(1, [x for foo foo foo], 3)";
+ String expr = "f(1, [x for foo foo foo foo], 3)";
FuncallExpression e = (FuncallExpression) parseExpression(expr);
assertContainsEvent("syntax error at 'foo'");
@@ -293,9 +293,9 @@ public class ParserTest extends EvaluationTestCase {
Ident arg1val = ((Ident) arg1.getValue());
assertEquals("$error$", arg1val.getName());
- assertLocation(5, 24, arg1val.getLocation());
- assertEquals("[x for foo foo foo]", expr.substring(5, 24));
- assertEquals(25, arg1val.getLocation().getEndLineAndColumn().getColumn());
+ assertLocation(5, 29, arg1val.getLocation());
+ assertEquals("[x for foo foo foo foo]", expr.substring(5, 28));
+ assertEquals(30, arg1val.getLocation().getEndLineAndColumn().getColumn());
IntegerLiteral arg2 = (IntegerLiteral) e.getArguments().get(2).getValue();
assertEquals(3, (int) arg2.getValue());