Control structures

This commit is contained in:
Andrey Breslav
2010-12-27 21:41:35 +03:00
parent 4cd1a55b9b
commit 408eb6fcdc
8 changed files with 896 additions and 13 deletions
@@ -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");
}
@@ -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)
@@ -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();
@@ -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);