From af85c99ffd3bb824617ca9fa66792f98a0c207a8 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 21 Aug 2012 19:08:41 +0400 Subject: [PATCH] KT-2627 Parse for with multiple range variables #KT-2627 Fixed --- .../lang/parsing/JetExpressionParsing.java | 27 +- .../jet/lang/parsing/JetParsing.java | 10 +- .../jet/lang/psi/JetForExpression.java | 7 +- .../lang/psi/JetMultiDeclarationEntry.java | 7 +- .../jet/lang/psi/JetVariableDeclaration.java | 3 +- compiler/testData/psi/ForWithMultiDecl.jet | 28 + compiler/testData/psi/ForWithMultiDecl.txt | 674 ++++++++++++++++++ grammar/src/class_members.grm | 6 +- grammar/src/control.grm | 2 +- 9 files changed, 738 insertions(+), 26 deletions(-) create mode 100644 compiler/testData/psi/ForWithMultiDecl.jet create mode 100644 compiler/testData/psi/ForWithMultiDecl.txt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 50eb3075b84..a8270eff304 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -1481,7 +1481,7 @@ public class JetExpressionParsing extends AbstractJetParsing { /* * for - * : "for" "(" attributes valOrVar? SimpleName (":" type)? "in" element ")" element + * : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression * ; * * TODO: empty loop body (at the end of the block)? @@ -1498,16 +1498,23 @@ public class JetExpressionParsing extends AbstractJetParsing { PsiBuilder.Marker parameter = mark(); if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD - if (!myJetParsing.parseIdeTemplate()) { - expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON)); - } - if (at(COLON)) { - advance(); // COLON - myJetParsing.parseTypeRef(); - } - parameter.done(LOOP_PARAMETER); + if (at(LPAR)) { + myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE)); - expect(IN_KEYWORD, "Expecting 'in'"); + parameter.done(MULTI_VARIABLE_DECLARATION); + } + else { + if (!myJetParsing.parseIdeTemplate()) { + expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON)); + } + if (at(COLON)) { + advance(); // COLON + myJetParsing.parseTypeRef(); + } + parameter.done(LOOP_PARAMETER); + } + + expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE)); PsiBuilder.Marker range = mark(); parseExpression(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java index be223c278f3..05e1fd9ab0d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -908,14 +908,14 @@ public class JetParsing extends AbstractJetParsing { /* * (SimpleName (":" type)){","} */ - private void parseMultiDeclarationName(TokenSet propertyNameFollow) { + public void parseMultiDeclarationName(TokenSet follow) { // Parsing multi-name, e.g. // val (a, b) = foo() myBuilder.disableNewlines(); advance(); // LPAR - TokenSet recoverySet = TokenSet.orSet(PARAMETER_NAME_RECOVERY_SET, propertyNameFollow); - if (!atSet(propertyNameFollow)) { + TokenSet recoverySet = TokenSet.orSet(PARAMETER_NAME_RECOVERY_SET, follow); + if (!atSet(follow)) { while (true) { if (at(COMMA)) { errorAndAdvance("Expecting a name"); @@ -929,7 +929,7 @@ public class JetParsing extends AbstractJetParsing { if (at(COLON)) { advance(); // COLON - parseTypeRef(); + parseTypeRef(follow); } property.done(MULTI_VARIABLE_DECLARATION_ENTRY); @@ -938,7 +938,7 @@ public class JetParsing extends AbstractJetParsing { } } - expect(RPAR, "Expecting ')'", propertyNameFollow); + expect(RPAR, "Expecting ')'", follow); myBuilder.restoreNewlinesState(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetForExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetForExpression.java index 540baaec95f..a548a4be5c6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetForExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetForExpression.java @@ -39,11 +39,16 @@ public class JetForExpression extends JetLoopExpression { return visitor.visitForExpression(this, data); } - @Nullable @IfNotParsed + @Nullable public JetParameter getLoopParameter() { return (JetParameter) findChildByType(JetNodeTypes.LOOP_PARAMETER); } + @Nullable + public JetMultiDeclaration getMultiParameter() { + return (JetMultiDeclaration) findChildByType(JetNodeTypes.MULTI_VARIABLE_DECLARATION); + } + @Nullable @IfNotParsed public JetExpression getLoopRange() { return findExpressionUnder(JetNodeTypes.LOOP_RANGE); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java index ceef453d1d0..05efa599703 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java @@ -18,13 +18,11 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.TokenSet; -import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lexer.JetTokens; -import static org.jetbrains.jet.lexer.JetTokens.EQ; import static org.jetbrains.jet.lexer.JetTokens.VAL_KEYWORD; import static org.jetbrains.jet.lexer.JetTokens.VAR_KEYWORD; @@ -69,11 +67,8 @@ public class JetMultiDeclarationEntry extends JetNamedDeclarationNotStubbed impl return parent; } - @NotNull @Override public ASTNode getValOrVarNode() { - ASTNode node = getParentNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD)); - assert node != null : "Val or var should always exist for property"; - return node; + return getParentNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVariableDeclaration.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVariableDeclaration.java index ecb5db24b36..3ddb2b5f62c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVariableDeclaration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVariableDeclaration.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -26,7 +25,7 @@ import org.jetbrains.annotations.Nullable; public interface JetVariableDeclaration extends JetDeclaration, JetWithExpressionInitializer, JetNamedDeclaration { boolean isVar(); - @NotNull + @Nullable ASTNode getValOrVarNode(); @Nullable diff --git a/compiler/testData/psi/ForWithMultiDecl.jet b/compiler/testData/psi/ForWithMultiDecl.jet new file mode 100644 index 00000000000..bad5b5c5f87 --- /dev/null +++ b/compiler/testData/psi/ForWithMultiDecl.jet @@ -0,0 +1,28 @@ +fun main() { + for ((a) in b) {} + for ((a, b) in b) {} + for ((a: Int, b: Int) in b) {} + for ((a: Int, b) in b) {} + for ((a, b: Int) in b) {} + + for (val (a) in b) {} + for (val (a, b) in b) {} + for (val (a: Int, b: Int) in b) {} + for (val (a: Int, b) in b) {} + for (val (a, b: Int) in b) {} + + for (var (a) in b) {} + for (var (a, b) in b) {} + for (var (a: Int, b: Int) in b) {} + for (var (a: Int, b) in b) {} + for (var (a, b: Int) in b) {} + + for ((a in b) {} + for ((a, ) in b) {} + for ((a: ) in b) {} + for ((a: , ) in b) {} + for ((, b: Int) in b) {} + + for ((a: in b) {} + for (( ) {} +} \ No newline at end of file diff --git a/compiler/testData/psi/ForWithMultiDecl.txt b/compiler/testData/psi/ForWithMultiDecl.txt new file mode 100644 index 00000000000..aa787f0df18 --- /dev/null +++ b/compiler/testData/psi/ForWithMultiDecl.txt @@ -0,0 +1,674 @@ +JetFile: ForWithMultiDecl.jet + NAMESPACE_HEADER + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('main') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiErrorElement:Expecting ')' + + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiErrorElement:Expecting a name + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(COMMA)(',') + PsiErrorElement:Expecting a name + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'in' + + PsiWhiteSpace(' ') + LOOP_RANGE + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + BLOCK + + PsiElement(RBRACE)('}') + PsiErrorElement:Expecting ')' + + PsiWhiteSpace('\n') + BODY + PsiErrorElement:Expecting an expression + + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/grammar/src/class_members.grm b/grammar/src/class_members.grm index 77861944f0a..95c00e0b6c8 100644 --- a/grammar/src/class_members.grm +++ b/grammar/src/class_members.grm @@ -85,10 +85,14 @@ variableDeclarationEntry : SimpleName (":" type)? ; +multipleVariableDeclarations + : "(" variableDeclarationEntry{","} ")" + ; + property : modifiers ("val" | "var") typeParameters? (type "." | annotations)? - ("(" variableDeclarationEntry{","} ")" | variableDeclarationEntry) + (multipleVariableDeclarations | variableDeclarationEntry) typeConstraints ("=" expression SEMI?)? (getter? setter? | setter? getter?) SEMI? diff --git a/grammar/src/control.grm b/grammar/src/control.grm index 66091a81b97..e1d285f885d 100644 --- a/grammar/src/control.grm +++ b/grammar/src/control.grm @@ -27,7 +27,7 @@ loop ; for - : "for" "(" annotations ("val" | "var")? SimpleName (":" type)? "in" expression ")" expression + : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression ; while