diff --git a/grammar/src/control.grm b/grammar/src/control.grm index 25e0d893b18..f6616ac4446 100644 --- a/grammar/src/control.grm +++ b/grammar/src/control.grm @@ -7,7 +7,7 @@ try ; catchBlock - : "catch" valueParameters block + : "catch" "(" attributes SimpleName ":" userType ")" block ; finallyBlock @@ -21,7 +21,7 @@ loop ; for - : "for" "(" valOrVar? (SimpleName | parameter) "in" expression ")" expression + : "for" "(" attributes valOrVar? SimpleName (":" type)? "in" expression ")" expression ; while diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index 4d9eebaabf9..4942fe437fb 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -74,6 +74,19 @@ public interface JetNodeTypes { JetNodeType THROW = new JetNodeType("THROW"); JetNodeType CONTINUE = new JetNodeType("CONTINUE"); JetNodeType BREAK = new JetNodeType("BREAK"); + JetNodeType IF = new JetNodeType("IF"); + JetNodeType CONDITION = new JetNodeType("CONDITION"); + JetNodeType THEN = new JetNodeType("THEN"); + JetNodeType ELSE = new JetNodeType("ELSE"); + JetNodeType TRY = new JetNodeType("TRY"); + JetNodeType CATCH = new JetNodeType("CATCH"); + JetNodeType FINALLY = new JetNodeType("FINALLY"); + JetNodeType FOR = new JetNodeType("FOR"); + JetNodeType WHILE = new JetNodeType("WHILE"); + JetNodeType DO_WHILE = new JetNodeType("DO_WHILE"); + JetNodeType LOOP_PARAMETER = new JetNodeType("LOOP_PARAMETER"); + JetNodeType LOOP_RANGE = new JetNodeType("LOOP_RANGE"); + JetNodeType BODY = new JetNodeType("BODY"); IElementType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME"); } diff --git a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java index a96be3eda31..d7a20a41172 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java @@ -42,6 +42,17 @@ import static org.jetbrains.jet.lexer.JetTokens.*; return false; } + protected boolean expectNoAdvance(JetToken expectation, String message) { + if (at(expectation)) { + advance(); // expectation + return true; + } + + error(message); + + return false; + } + protected void errorWithRecovery(String message, TokenSet recoverySet) { IElementType tt = tt(); if (recoverySet == null || recoverySet.contains(tt) diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 27cbce8f7aa..8207e34903c 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -74,19 +74,19 @@ public class JetExpressionParsing extends AbstractJetParsing { parseJump(BREAK); } else if (at(IF_KEYWORD)) { - // TODO + parseIf(); } else if (at(TRY_KEYWORD)) { - // TODO + parseTry(); } else if (at(FOR_KEYWORD)) { - // TODO + parseFor(); } else if (at(WHILE_KEYWORD)) { - // TODO + parseWhile(); } else if (at(DO_KEYWORD)) { - // TODO + parseDoWhile(); } else if (atSet(TokenSet.create( CLASS_KEYWORD, @@ -100,6 +100,10 @@ public class JetExpressionParsing extends AbstractJetParsing { else if (at(IDENTIFIER)) { advance(); // TODO } + else if (at(LBRACE)) { + // TODO + myJetParsing.parseBlock(); + } else if (at(INTEGER_LITERAL)) { parseOneTokenExpression(INTEGER_CONSTANT); } @@ -124,6 +128,183 @@ public class JetExpressionParsing extends AbstractJetParsing { else if (at(NULL_KEYWORD)) { parseOneTokenExpression(NULL); } + else { + errorAndAdvance("Expecting an expression"); + } + } + + /* + * doWhile + * : "do" expression "while" "(" expression ")" + * ; + */ + private void parseDoWhile() { + assert at(DO_KEYWORD); + + PsiBuilder.Marker loop = mark(); + + advance(); // DO_KEYWORD + + parseControlStructureBody(); + + expect(WHILE_KEYWORD, "Expecting 'while' followed by a post-condition"); + + parseCondition(); + + loop.done(DO_WHILE); + } + + /* + * while + * : "while" "(" expression ")" expression + * ; + */ + private void parseWhile() { + assert at(WHILE_KEYWORD); + + PsiBuilder.Marker loop = mark(); + + advance(); // WHILE_KEYWORD + + parseCondition(); + + parseControlStructureBody(); + + loop.done(WHILE); + } + + /* + * for + * : "for" "(" attributes valOrVar? SimpleName (":" type)? "in" expression ")" expression + * ; + */ + private void parseFor() { + assert at(FOR_KEYWORD); + + PsiBuilder.Marker loop = mark(); + + advance(); // FOR_KEYWORD + + expect(LPAR, "Expecting '(' to open a loop range", TokenSet.create(RPAR, VAL_KEYWORD, VAR_KEYWORD, IDENTIFIER)); + + PsiBuilder.Marker parameter = mark(); + if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD + 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'"); + + PsiBuilder.Marker range = mark(); + parseExpression(); + range.done(LOOP_RANGE); + + expectNoAdvance(RPAR, "Expecting ')'"); + + parseControlStructureBody(); + + loop.done(FOR); + } + + /* + * expression + */ + private void parseControlStructureBody() { + PsiBuilder.Marker body = mark(); + parseExpression(); + body.done(BODY); + + // TODO: empty body? + } + + /* + * try + * : "try" block catchBlock* finallyBlock? + * ; + * catchBlock + * : "catch" "(" attributes SimpleName ":" userType ")" block + * ; + * + * finallyBlock + * : "finally" block + * ; + */ + private void parseTry() { + assert at(TRY_KEYWORD); + + PsiBuilder.Marker tryExpression = mark(); + + advance(); // TRY_KEYWORD + + myJetParsing.parseBlock(); + + while (at(CATCH_KEYWORD)) { + PsiBuilder.Marker catchBlock = mark(); + advance(); // CATCH_KEYWORD + + myJetParsing.parseValueParameterList(false, TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD)); + + myJetParsing.parseBlock(); + catchBlock.done(CATCH); + } + + if (at(FINALLY_KEYWORD)) { + PsiBuilder.Marker finallyBlock = mark(); + + advance(); // FINALLY_KEYWORD + + myJetParsing.parseBlock(); + + finallyBlock.done(FINALLY); + } + + tryExpression.done(TRY); + } + + /* + * if + * : "if" "(" expression ")" expression ("else" expression)? + * ; + */ + private void parseIf() { + assert at(IF_KEYWORD); + + PsiBuilder.Marker marker = mark(); + + advance(); //IF_KEYWORD + + parseCondition(); + + // TODO: empty body? + PsiBuilder.Marker thenBranch = mark(); + parseExpression(); + thenBranch.done(THEN); + + if (at(ELSE_KEYWORD)) { + advance(); // ELSE_KEYWORD + + PsiBuilder.Marker elseBranch = mark(); + parseExpression(); + elseBranch.done(ELSE); + } + + marker.done(IF); + } + + /* + * "(" expression ")" + */ + private void parseCondition() { + expect(LPAR, "Expecting a condition in parentheses '(...)'"); + + PsiBuilder.Marker condition = mark(); + parseExpression(); + condition.done(CONDITION); + + expect(RPAR, "Expecting ')"); } /* @@ -232,7 +413,7 @@ public class JetExpressionParsing extends AbstractJetParsing { advance(); // LBRACKET - // If this is an emty map "[:]" + // If this is an empty map "[:]" if (at(COLON)) { advance(); // COLON expect(RBRACKET, "Expecting ']' to close an empty map literal '[:]'"); @@ -240,6 +421,13 @@ public class JetExpressionParsing extends AbstractJetParsing { return; } + // If this is an empty list "[]" + if (at(RBRACKET)) { + advance(); // RBRACKET + literal.done(LIST_LITERAL); + return; + } + PsiBuilder.Marker item = mark(); parseExpression(); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 56e306ac565..dc98202eb41 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -857,12 +857,10 @@ public class JetParsing extends AbstractJetParsing { * : "{" (expression SEMI)* "}" * ; */ - private void parseBlock() { - assert at(LBRACE); - + public void parseBlock() { PsiBuilder.Marker block = mark(); - advance(); // LBRACE + expect(LBRACE, "Expecting '{' to open a block"); while (!eof() && !at(RBRACE)) { myExpressionParsing.parseExpression(); @@ -1300,7 +1298,7 @@ public class JetParsing extends AbstractJetParsing { * : parameter ("=" expression)? * ; */ - private void parseValueParameterList(boolean isFunctionTypeContents, TokenSet recoverySet) { + public void parseValueParameterList(boolean isFunctionTypeContents, TokenSet recoverySet) { PsiBuilder.Marker parameters = mark(); expect(LPAR, "Expecting '(", recoverySet); diff --git a/idea/testData/psi/ControlStructures.jet b/idea/testData/psi/ControlStructures.jet new file mode 100644 index 00000000000..15bbc908069 --- /dev/null +++ b/idea/testData/psi/ControlStructures.jet @@ -0,0 +1,80 @@ + +fun a( + a : foo = throw new Foo, + a : foo = return 10, + a : foo = break, + a : foo = break la, + a : foo = continue, + a : foo = continue la, + a : foo = if (10) foo else bar, + a : foo = if (10) foo +) { + return 10 + return + 10 + break + la + break la + continue + la + continue la + if (foo) + if (foo) + bar + else + foo + else if (foo) + bar + else + bar + + try { + + } + catch (Foo : Bar) { + + } + try { + + } + catch (Foo : Bar) { + + } + catch (Foo : Bar) { + + } + catch (Foo : Bar) { + + } + try { + + } + catch (Foo : Bar) { + + } + catch (Foo : Bar) { + + } + finally { + + } + try { + + } + finally { + + } + + for (val x in foo) a + for (x in foo) a + for (val x in [1..10]) a + for (x in [1..10]) a + for (val x : Int in [1..10]) a + for (x : Int in [1..10]) {} + + while (true) {} + + do { + + } while (false) +} \ No newline at end of file diff --git a/idea/testData/psi/ControlStructures.txt b/idea/testData/psi/ControlStructures.txt new file mode 100644 index 00000000000..a5e18b3b154 --- /dev/null +++ b/idea/testData/psi/ControlStructures.txt @@ -0,0 +1,592 @@ +JetFile: ControlStructures.jet + NAMESPACE + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') + TYPE_PARAMETER_LIST + + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + THROW + PsiElement(throw)('throw') + PsiWhiteSpace(' ') + NEW + PsiElement(new)('new') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Foo') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + BREAK + PsiElement(break)('break') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + BREAK + PsiElement(break)('break') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('la') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + CONTINUE + PsiElement(continue)('continue') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + CONTINUE + PsiElement(continue)('continue') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('la') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + THEN + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(else)('else') + PsiWhiteSpace(' ') + ELSE + PsiElement(IDENTIFIER)('bar') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + THEN + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace('\n') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiWhiteSpace('\n ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace('\n ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiWhiteSpace('\n ') + BREAK + PsiElement(break)('break') + PsiWhiteSpace('\n ') + PsiElement(IDENTIFIER)('la') + PsiWhiteSpace('\n ') + BREAK + PsiElement(break)('break') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('la') + PsiWhiteSpace('\n ') + CONTINUE + PsiElement(continue)('continue') + PsiWhiteSpace('\n ') + PsiElement(IDENTIFIER)('la') + PsiWhiteSpace('\n ') + CONTINUE + PsiElement(continue)('continue') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('la') + PsiWhiteSpace('\n ') + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + PsiElement(IDENTIFIER)('foo') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + THEN + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + PsiElement(IDENTIFIER)('foo') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + THEN + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n ') + PsiElement(else)('else') + PsiWhiteSpace('\n ') + ELSE + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace('\n ') + PsiElement(else)('else') + PsiWhiteSpace(' ') + ELSE + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + PsiElement(IDENTIFIER)('foo') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + THEN + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n ') + PsiElement(else)('else') + PsiWhiteSpace('\n ') + ELSE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('Foo') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Bar') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('Foo') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Bar') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('Foo') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Bar') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('Foo') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Bar') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('Foo') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Bar') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('Foo') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Bar') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FINALLY + PsiElement(finally)('finally') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FINALLY + PsiElement(finally)('finally') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + LOOP_PARAMETER + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + PsiElement(IDENTIFIER)('foo') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + LOOP_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + PsiElement(IDENTIFIER)('foo') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + LOOP_PARAMETER + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + RANGE_LITERAL + PsiElement(LBRACKET)('[') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RANGE)('..') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(RBRACKET)(']') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + LOOP_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + RANGE_LITERAL + PsiElement(LBRACKET)('[') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RANGE)('..') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(RBRACKET)(']') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + LOOP_PARAMETER + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + RANGE_LITERAL + PsiElement(LBRACKET)('[') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RANGE)('..') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(RBRACKET)(']') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + LOOP_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + RANGE_LITERAL + PsiElement(LBRACKET)('[') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RANGE)('..') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('10') + PsiElement(RBRACKET)(']') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + WHILE + PsiElement(while)('while') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + DO_WHILE + PsiElement(do)('do') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + PsiElement(while)('while') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + BOOLEAN_CONSTANT + PsiElement(false)('false') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java b/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java index aae2913ae5d..cae2f18f92b 100644 --- a/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java +++ b/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java @@ -60,4 +60,5 @@ public class JetParsingTest extends ParsingTestCase { public void testTypeConstraints() throws Exception {doTest(true);} public void testEnums() throws Exception {doTest(true);} public void testSimpleExpressions() throws Exception {doTest(true);} + public void testControlStructures() throws Exception {doTest(true);} }