Local declarations

This commit is contained in:
Andrey Breslav
2010-12-29 18:08:47 +03:00
parent 88b5c26fe3
commit 01297cc926
12 changed files with 321 additions and 61 deletions
@@ -102,9 +102,20 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
return true;
}
}
if (expectation == IDENTIFIER && token instanceof JetKeywordToken) {
JetKeywordToken keywordToken = (JetKeywordToken) token;
if (keywordToken.isSoft()) {
myBuilder.remapCurrentToken(IDENTIFIER);
return true;
}
}
return false;
}
protected boolean atSet(IElementType... tokens) {
return atSet(TokenSet.create(tokens));
}
protected boolean atSet(final TokenSet set) {
IElementType token = tt();
if (set.contains(token)) return true;
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.jet.JetNodeType;
@@ -106,19 +107,21 @@ public class JetExpressionParsing extends AbstractJetParsing {
else if (at(NULL_KEYWORD)) {
parseOneTokenExpression(NULL);
}
else if (atSet(TokenSet.create(
CLASS_KEYWORD,
EXTENSION_KEYWORD,
FUN_KEYWORD,
VAL_KEYWORD,
VAR_KEYWORD,
TYPE_KEYWORD))) {
// modifiers
// attributes
// TODO
else if (atSet(CLASS_KEYWORD, EXTENSION_KEYWORD, FUN_KEYWORD, VAL_KEYWORD,
VAR_KEYWORD, TYPE_KEYWORD, DECOMPOSER_KEYWORD)) {
parseLocalDeclaration();
}
else if (at(LBRACKET)) {
if (!parseLocalDeclaration()) {
PsiBuilder.Marker attributes = mark();
myJetParsing.parseAttributeList();
attributes.error("Attributes are only allowed on declarations");
}
}
else if (at(IDENTIFIER)) {
advance(); // TODO
if (!parseLocalDeclaration()) {
expect(IDENTIFIER, "[Internal error: should never occur]"); // TODO
}
}
else if (at(LBRACE)) {
// TODO
@@ -131,6 +134,47 @@ public class JetExpressionParsing extends AbstractJetParsing {
// TODO: Binary operations
}
private boolean parseLocalDeclaration() {
PsiBuilder.Marker decls = mark();
JetParsing.EnumDetector enumDetector = new JetParsing.EnumDetector();
myJetParsing.parseModifierList(enumDetector);
JetNodeType declType = parseLocalDeclarationRest(enumDetector.isEnum());
if (declType != null) {
decls.done(declType);
return true;
} else {
decls.rollbackTo();
return false;
}
}
private JetNodeType parseLocalDeclarationRest(boolean isEnum) {
IElementType keywordToken = tt();
JetNodeType declType = null;
if (keywordToken == CLASS_KEYWORD) {
declType = myJetParsing.parseClass(isEnum);
}
else if (keywordToken == EXTENSION_KEYWORD) {
declType = myJetParsing.parseExtension();
}
else if (keywordToken == FUN_KEYWORD) {
declType = myJetParsing.parseFunction();
}
else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
declType = myJetParsing.parseProperty();
}
else if (keywordToken == TYPE_KEYWORD) {
declType = myJetParsing.parseTypeDef();
}
else if (keywordToken == DECOMPOSER_KEYWORD) {
declType = myJetParsing.parseDecomposer();
}
return declType;
}
/*
* doWhile
* : "do" expression "while" "(" expression ")"
@@ -213,7 +213,7 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers "decomposer" (type ".")? SimpleName? "(" (attributes SimpleName){","}? ")" // Public properties only
* ;
*/
private JetNodeType parseDecomposer() {
public JetNodeType parseDecomposer() {
assert at(DECOMPOSER_KEYWORD);
advance(); // DECOMPOSER_KEYWORD
@@ -274,7 +274,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* (modifier | attribute)*
*/
private void parseModifierList() {
public void parseModifierList() {
parseModifierList(null);
}
@@ -283,7 +283,7 @@ public class JetParsing extends AbstractJetParsing {
*
* Feeds modifiers (not attributes) into the passed consumer, if it is not null
*/
private void parseModifierList(Consumer<IElementType> tokenConsumer) {
public void parseModifierList(Consumer<IElementType> tokenConsumer) {
PsiBuilder.Marker list = mark();
boolean empty = true;
while (!eof()) {
@@ -391,7 +391,7 @@ public class JetParsing extends AbstractJetParsing {
* (classBody? | enumClassBody)
* ;
*/
private JetNodeType parseClass(boolean enumClass) {
public JetNodeType parseClass(boolean enumClass) {
assert at(CLASS_KEYWORD);
advance(); // CLASS_KEYWORD
@@ -664,7 +664,7 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers "type" SimpleName typeParameters? "=" type
* ;
*/
private JetNodeType parseTypeDef() {
public JetNodeType parseTypeDef() {
assert at(TYPE_KEYWORD);
advance(); // TYPE_KEYWORD
@@ -688,32 +688,31 @@ public class JetParsing extends AbstractJetParsing {
* (getter? setter? | setter? getter?) SEMI?
* ;
*/
private JetNodeType parseProperty() {
public JetNodeType parseProperty() {
assert at(VAL_KEYWORD) || at(VAR_KEYWORD);
advance(); // VAL_KEYWORD or VAR_KEYWORD
// TODO: EOL_OR_SEMICOLON is too restrictive here
TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, SEMICOLON);
// int lastDot = findLastBefore(TokenSet.create(DOT), propertyNameFollow, true);
// TODO: constant
int lastDot = matchTokenStreamPredicate(new FirstBefore(new TokenStreamPredicate() {
@Override
public boolean matching(boolean topLevel) {
return topLevel
&& at(DOT);
}
}, new TokenStreamPredicate() {
@Override
public boolean matching(boolean topLevel) {
if (lookahead(1) == IDENTIFIER) {
IElementType lookahead2 = lookahead(2);
return lookahead2 != LT && lookahead2 != DOT;
}
return false;
}
}));
int lastDot = matchTokenStreamPredicate(new FirstBefore(
new TokenStreamPredicate() {
@Override
public boolean matching(boolean topLevel) {
return topLevel
&& at(DOT);
}
}, new TokenStreamPredicate() {
@Override
public boolean matching(boolean topLevel) {
if (lookahead(1) == IDENTIFIER) {
IElementType lookahead2 = lookahead(2);
return lookahead2 != LT && lookahead2 != DOT;
}
return false;
}
}));
if (lastDot == -1) {
parseAttributeList();
@@ -806,7 +805,7 @@ public class JetParsing extends AbstractJetParsing {
* : attributes SimpleName typeParameters? functionParameters (":" type)? functionBody?
* ;
*/
private JetNodeType parseFunction() {
public JetNodeType parseFunction() {
assert at(FUN_KEYWORD);
advance(); // FUN_KEYWORD
@@ -892,7 +891,7 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers "extension" SimpleName? typeParameters? "for" type classBody? // properties cannot be lazy, cannot have backing fields
* ;
*/
private JetNodeType parseExtension() {
public JetNodeType parseExtension() {
assert at(EXTENSION_KEYWORD);
advance(); // EXTENSION_KEYWORD
@@ -975,7 +974,7 @@ public class JetParsing extends AbstractJetParsing {
* : attributeAnnotation*
* ;
*/
private void parseAttributeList() {
public void parseAttributeList() {
while (at(LBRACKET)) parseAttributeAnnotation();
}
@@ -1382,7 +1381,7 @@ public class JetParsing extends AbstractJetParsing {
return new JetParsing(new TruncatedSemanticWhitespaceAwarePsiBuilder(myBuilder, eofPosition));
}
private static class EnumDetector implements Consumer<IElementType> {
/*package*/ static class EnumDetector implements Consumer<IElementType> {
private boolean myEnum = false;
+16
View File
@@ -0,0 +1,16 @@
fun foo() {
lazy
1
[a] abstract class foof {}
abstract [a] class foof {}
lazy val foo = 5
[a] var foo = 4
type f = {T.() : ()}
virtual extension foo for bar {
}
decomposer T.foo(bar)
}
+158
View File
@@ -0,0 +1,158 @@
JetFile: LocalDeclarations.jet
NAMESPACE
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
TYPE_PARAMETER_LIST
<empty list>
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiElement(IDENTIFIER)('lazy')
PsiWhiteSpace('\n ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n ')
CLASS
MODIFIER_LIST
ATTRIBUTE_ANNOTATION
PsiElement(LBRACKET)('[')
ATTRIBUTE
USER_TYPE
PsiElement(IDENTIFIER)('a')
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PsiElement(abstract)('abstract')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foof')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
CLASS_BODY
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
CLASS
MODIFIER_LIST
PsiElement(abstract)('abstract')
PsiWhiteSpace(' ')
ATTRIBUTE_ANNOTATION
PsiElement(LBRACKET)('[')
ATTRIBUTE
USER_TYPE
PsiElement(IDENTIFIER)('a')
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foof')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
CLASS_BODY
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
PROPERTY
MODIFIER_LIST
PsiElement(lazy)('lazy')
PsiWhiteSpace(' ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('5')
PsiWhiteSpace('\n ')
PROPERTY
MODIFIER_LIST
ATTRIBUTE_ANNOTATION
PsiElement(LBRACKET)('[')
ATTRIBUTE
USER_TYPE
PsiElement(IDENTIFIER)('a')
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('4')
PsiWhiteSpace('\n ')
TYPEDEF
PsiElement(type)('type')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('f')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
TYPE_REFERENCE
FUNCTION_TYPE
PsiElement(LBRACE)('{')
RECEIVER_TYPE
TYPE_REFERENCE
USER_TYPE
PsiElement(IDENTIFIER)('T')
PsiElement(DOT)('.')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
TUPLE_TYPE
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
EXTENSION
MODIFIER_LIST
PsiElement(virtual)('virtual')
PsiWhiteSpace(' ')
PsiElement(extension)('extension')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
PsiElement(for)('for')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
DECOMPOSER
PsiElement(decomposer)('decomposer')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
PsiElement(IDENTIFIER)('T')
PsiElement(DOT)('.')
USER_TYPE
PsiElement(IDENTIFIER)('foo')
DECOMPOSER_PROPERTY_LIST
PsiElement(LPAR)('(')
PsiElement(IDENTIFIER)('bar')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,5 @@
fun foo() {
[a]
1
[a]
}
@@ -0,0 +1,35 @@
JetFile: LocalDeclarations_ERR.jet
NAMESPACE
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
TYPE_PARAMETER_LIST
<empty list>
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiErrorElement:Attributes are only allowed on declarations
ATTRIBUTE_ANNOTATION
PsiElement(LBRACKET)('[')
ATTRIBUTE
USER_TYPE
PsiElement(IDENTIFIER)('a')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n ')
PsiErrorElement:Attributes are only allowed on declarations
ATTRIBUTE_ANNOTATION
PsiElement(LBRACKET)('[')
ATTRIBUTE
USER_TYPE
PsiElement(IDENTIFIER)('a')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -47,6 +47,8 @@ public class JetParsingTest extends ParsingTestCase {
public void testImports() throws Exception {doTest(true);}
public void testImports_ERR() throws Exception {doTest(true);}
public void testImportSoftKW() throws Exception {doTest(true);}
public void testLocalDeclarations() throws Exception {doTest(true);}
public void testLocalDeclarations_ERR() throws Exception {doTest(true);}
public void testNamespaceBlock_ERR() throws Exception {doTest(true);}
public void testNamespaceBlock() throws Exception {doTest(true);}
public void testProperties() throws Exception {doTest(true);}