From d4551a61bf55b9716a2bd062dd3f3145db4b2fc4 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 25 Apr 2011 20:32:12 +0400 Subject: [PATCH] Declarations are not parsed as expressions any more (JET-1) --- grammar/src/class_members.grm | 2 +- grammar/src/expressions.grm | 17 ++++-- .../jet/lang/parsing/AbstractJetParsing.java | 4 +- .../lang/parsing/JetExpressionParsing.java | 60 +++++++++++-------- .../jet/lang/parsing/JetParsing.java | 2 +- idea/testData/psi/ModifierAsSelector.jet | 5 ++ idea/testData/psi/ModifierAsSelector.txt | 47 +++++++++++++++ 7 files changed, 104 insertions(+), 33 deletions(-) create mode 100644 idea/testData/psi/ModifierAsSelector.jet create mode 100644 idea/testData/psi/ModifierAsSelector.txt diff --git a/grammar/src/class_members.grm b/grammar/src/class_members.grm index 538d1767f30..576c0fd0e8b 100644 --- a/grammar/src/class_members.grm +++ b/grammar/src/class_members.grm @@ -63,7 +63,7 @@ initializer ; block - : "{" expressions "}" + : "{" statements "}" ; function diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm index 78021744d51..f77625fb414 100644 --- a/grammar/src/expressions.grm +++ b/grammar/src/expressions.grm @@ -89,7 +89,7 @@ atomicExpression : "typeof" "(" expression ")" : "new" constructorInvocation : objectLiteral - : declaration +// : declaration : jump : loop : SimpleName @@ -126,6 +126,11 @@ declaration : typedef ; +statement + : declaration + : expression + ; + multiplicativeOperation : "*" : "/" : "%" ; @@ -215,13 +220,13 @@ tupleLiteral // Ambiguity when after a SimpleName (infix call). In this case (e) ; functionLiteral // one can use "it" as a parameter name - : "{" expressions "}" - : "{" (type ".")? modifiers SimpleName "=>" expressions "}" - : "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "=>" expressions "}" + : "{" statements "}" + : "{" (type ".")? modifiers SimpleName "=>" statements "}" + : "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "=>" statements "}" ; -expressions - : SEMI* expression{SEMI+} SEMI* +statements + : SEMI* statement{SEMI+} SEMI* ; constructorInvocation diff --git a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java index 3a0b600f394..c9ce19b2867 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java @@ -172,11 +172,13 @@ import static org.jetbrains.jet.lexer.JetTokens.*; myBuilder.remapCurrentToken(keywordToken); return true; } - } else { + } + else { // We know at this point that set does not contain token if (set.contains(IDENTIFIER) && token instanceof JetKeywordToken) { if (((JetKeywordToken) token).isSoft()) { myBuilder.remapCurrentToken(IDENTIFIER); + return true; } } } diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 3c14d0047f7..2484e5db4d6 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -31,7 +31,7 @@ public class JetExpressionParsing extends AbstractJetParsing { COLON ); - /*package*/ static final TokenSet EXPRESSION_FIRST = TokenSet.orSet(TokenSet.create( + /*package*/ static final TokenSet EXPRESSION_FIRST = TokenSet.create( // Prefix MINUS, PLUS, MINUSMINUS, PLUSPLUS, EXCL, LBRACKET, LABEL_IDENTIFIER, AT, ATAT, // Atomic @@ -57,14 +57,6 @@ public class JetExpressionParsing extends AbstractJetParsing { NEW_KEYWORD, // new OBJECT_KEYWORD, // object - // declaration - LBRACKET, // attribute - FUN_KEYWORD, - VAL_KEYWORD, VAR_KEYWORD, - EXTENSION_KEYWORD, - CLASS_KEYWORD, - TYPE_KEYWORD, - // jump THROW_KEYWORD, RETURN_KEYWORD, @@ -80,7 +72,21 @@ public class JetExpressionParsing extends AbstractJetParsing { FIELD_IDENTIFIER, // Field reference NAMESPACE_KEYWORD // for absolute qualified names - ), MODIFIER_KEYWORDS); + ); + + private static final TokenSet STATEMENT_FIRST = TokenSet.orSet( + EXPRESSION_FIRST, + TokenSet.create( + // declaration + LBRACKET, // attribute + FUN_KEYWORD, + VAL_KEYWORD, VAR_KEYWORD, + EXTENSION_KEYWORD, + CLASS_KEYWORD, + TYPE_KEYWORD + ), + MODIFIER_KEYWORDS + ); /*package*/ static final TokenSet EXPRESSION_FOLLOW = TokenSet.create( SEMICOLON, DOUBLE_ARROW, COMMA, RBRACE, RPAR, RBRACKET @@ -523,13 +529,7 @@ public class JetExpressionParsing extends AbstractJetParsing { parseSimpleNameExpression(); } else if (at(IDENTIFIER)) { - if (JetParsing.MODIFIER_KEYWORD_MAP.containsKey(myBuilder.getTokenText())) { - if (!parseLocalDeclaration()) { - parseSimpleNameExpression(); - } - } else { - parseSimpleNameExpression(); - } + parseSimpleNameExpression(); } else if (at(LBRACE)) { parseFunctionLiteral(); @@ -1022,7 +1022,7 @@ public class JetExpressionParsing extends AbstractJetParsing { } PsiBuilder.Marker body = mark(); - parseExpressions(); + parseStatements(); body.done(BODY); expect(RBRACE, "Expecting '}'"); @@ -1073,27 +1073,39 @@ public class JetExpressionParsing extends AbstractJetParsing { /* * expressions - * : SEMI* element{SEMI+} SEMI* + * : SEMI* statement{SEMI+} SEMI* */ - public void parseExpressions() { + public void parseStatements() { while (at(SEMICOLON)) advance(); // SEMICOLON while (!eof() && !at(RBRACE)) { - if (!atSet(EXPRESSION_FIRST)) { + if (!atSet(STATEMENT_FIRST)) { errorAndAdvance("Expecting an element"); } - if (atSet(EXPRESSION_FIRST)) { - parseExpression(); + if (atSet(STATEMENT_FIRST)) { + parseStatement(); } if (at(SEMICOLON)) { while (at(SEMICOLON)) advance(); // SEMICOLON } else if (at(RBRACE)) { break; } else if (!myBuilder.newlineBeforeCurrentToken()) { - errorUntil("Unexpected tokens (use ';' to separate expressions on the same line", TokenSet.create(EOL_OR_SEMICOLON)); + errorUntil("Unexpected tokens (use ';' to separate expressions on the same line)", TokenSet.create(EOL_OR_SEMICOLON)); } } } + /* + * statement + * : expression + * : declaration + * ; + */ + private void parseStatement() { + if (!parseLocalDeclaration()) { + parseExpression(); + } + } + /* * declaration * : function diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 0ccc475b30d..2f6cd5b0f22 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -921,7 +921,7 @@ public class JetParsing extends AbstractJetParsing { myBuilder.enableNewlines(); expect(LBRACE, "Expecting '{' to open a block"); - myExpressionParsing.parseExpressions(); + myExpressionParsing.parseStatements(); expect(RBRACE, "Expecting '}"); myBuilder.restoreNewlinesState(); diff --git a/idea/testData/psi/ModifierAsSelector.jet b/idea/testData/psi/ModifierAsSelector.jet new file mode 100644 index 00000000000..137426ea38b --- /dev/null +++ b/idea/testData/psi/ModifierAsSelector.jet @@ -0,0 +1,5 @@ +// JET-1 + +val z = System.out + +fun foo() { throw new Exception(); } diff --git a/idea/testData/psi/ModifierAsSelector.txt b/idea/testData/psi/ModifierAsSelector.txt new file mode 100644 index 00000000000..ac832441ecf --- /dev/null +++ b/idea/testData/psi/ModifierAsSelector.txt @@ -0,0 +1,47 @@ +JetFile: ModifierAsSelector.jet + PsiComment(EOL_COMMENT)('// JET-1') + PsiWhiteSpace('\n\n') + NAMESPACE + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('z') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('System') + PsiElement(DOT)('.') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('out') + PsiWhiteSpace('\n\n') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + THROW + PsiElement(throw)('throw') + PsiWhiteSpace(' ') + NEW + PsiElement(new)('new') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Exception') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') \ No newline at end of file