diff --git a/grammar/src/class_members.grm b/grammar/src/class_members.grm index e83585b7edf..4fb85050718 100644 --- a/grammar/src/class_members.grm +++ b/grammar/src/class_members.grm @@ -71,11 +71,11 @@ block ; decomposer // TODO: consider other names - : attributes "decomposer" SimpleName "(" (attributes SimpleName){","} ")" // Public properties only + : attributes "decomposer" (type ".")? SimpleName "(" (attributes SimpleName){","} ")" // Public properties only ; function - : modifiers "fun" functionRest + : modifiers "fun" (type ".")? functionRest ; functionRest @@ -88,7 +88,7 @@ functionBody ; property - : modifiers ("val" | "var") propertyRest + : modifiers ("val" | "var") (type ".")? propertyRest ; propertyRest diff --git a/grammar/src/extension.grm b/grammar/src/extension.grm deleted file mode 100644 index fbf10f12ac9..00000000000 --- a/grammar/src/extension.grm +++ /dev/null @@ -1,22 +0,0 @@ -extension - : completeExtension - : extensionMethod - : extensionProperty - : extensionDecomposer - ; - -completeExtension - : modifiers "extension" SimpleName? typeParameters? "for" type classBody? // properties cannot be lazy, cannot have backing fields - ; - -extensionMethod - : modifiers "fun" type "." functionRest - ; - -extensionProperty - : modifiers ("val" | "var") type "." propertyRest // Extension property cannot be lazy - ; - -extensionDecomposer - : attributes "decomposer" (type ".")? SimpleName "(" attributes SimpleName{","} ")" // Public properties only - ; \ No newline at end of file diff --git a/grammar/src/toplevel.grm b/grammar/src/toplevel.grm index 0ca75e87f61..0785c684279 100644 --- a/grammar/src/toplevel.grm +++ b/grammar/src/toplevel.grm @@ -25,6 +25,7 @@ toplevelObject : function : property : typedef + : decomposer ; namespace @@ -36,4 +37,8 @@ namespace typedef : modifiers "type" SimpleName typeParameters? "=" type - ; \ No newline at end of file + ; + +extension + : modifiers "extension" SimpleName? typeParameters? "for" type classBody? // properties cannot be lazy, cannot have backing fields + ; diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index f850d62373c..b9948101c82 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -16,6 +16,7 @@ public interface JetNodeTypes { JetNodeType FUN = new JetNodeType("FUN"); JetNodeType EXTENSION = new JetNodeType("EXTENSION"); JetNodeType TYPEDEF = new JetNodeType("TYPEDEF"); + JetNodeType DECOMPOSER = new JetNodeType("DECOMPOSER"); JetNodeType TYPE_PARAMETER_LIST = new JetNodeType("TYPE_PARAMETER_LIST"); JetNodeType TYPE_PARAMETER = new JetNodeType("TYPE_PARAMETER"); JetNodeType PRIMARY_CONSTRUCTOR_PARAMETERS_LIST = new JetNodeType("PRIMARY_CONSTRUCTOR_PARAMETERS_LIST"); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index bcceec501f3..968d7285488 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -26,7 +26,7 @@ public class JetParsing { } private static final TokenSet TOPLEVEL_OBJECT_FIRST = TokenSet.create(TYPE_KEYWORD, CLASS_KEYWORD, - EXTENSION_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, REF_KEYWORD, NAMESPACE_KEYWORD); + EXTENSION_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, REF_KEYWORD, NAMESPACE_KEYWORD, DECOMPOSER_KEYWORD); private static final TokenSet CLASS_NAME_RECOVERY_SET = TokenSet.orSet(TokenSet.create(LT, WRAPS_KEYWORD, LPAR, COLON, LBRACE), TOPLEVEL_OBJECT_FIRST); private static final TokenSet TYPE_PARAMETER_GT_RECOVERY_SET = TokenSet.create(WHERE_KEYWORD, WRAPS_KEYWORD, LPAR, COLON, LBRACE, GT); @@ -199,6 +199,9 @@ public class JetParsing { else if (keywordToken == TYPE_KEYWORD) { declType = parseTypedef(); } + else if (keywordToken == DECOMPOSER_KEYWORD) { + declType = parseDecomposer(); + } if (declType == null) { errorAndAdvance("Expecting namespace or top level declaration"); @@ -209,6 +212,16 @@ public class JetParsing { } } + /* + * decomposer + * : attributes "decomposer" (type ".")? SimpleName "(" (attributes SimpleName){","} ")" // Public properties only + * ; + */ + private JetNodeType parseDecomposer() { + // TODO + return DECOMPOSER; + } + /* * modifier * : "virtual" @@ -330,13 +343,15 @@ public class JetParsing { */ private void parseValueArgument() { PsiBuilder.Marker argument = mark(); + JetNodeType type = VALUE_ARGUMENT; if (at(IDENTIFIER) && lookahead(1) == EQ) { - advance(); // IDENTIFIER - advance(); // EQ + advance(); // IDENTIFIER + advance(); // EQ + type = NAMED_ARGUMENT; } if (at(OUT_KEYWORD) || at(REF_KEYWORD)) advance(); // REF or OUT parseExpression(); - argument.done(VALUE_ARGUMENT); + argument.done(type); } /* @@ -374,6 +389,16 @@ public class JetParsing { return NAMESPACE; } + /* + * class + * : modifiers "class" SimpleName + * typeParameters? + * "wraps"? + * ("(" primaryConstructorParameter{","} ")")? + * (":" attributes delegationSpecifier{","})? + * classBody? + * ; + */ private JetNodeType parseClass() { assert at(CLASS_KEYWORD); advance(); // CLASS_KEYWORD @@ -398,6 +423,11 @@ public class JetParsing { return CLASS; } + /* + * classBody + * : ("{" memberDeclaration{","} "}")? + * ; + */ private void parseClassBody() { assert at(LBRACE); PsiBuilder.Marker body = mark(); @@ -436,25 +466,51 @@ public class JetParsing { return TYPEDEF; } + /* + * property + * : modifiers ("val" | "var") (type ".")? propertyRest + * ; + */ private JetNodeType parseProperty() { advance(); // TODO return PROPERTY; } + /* + * function + * : modifiers "fun" (type ".")? functionRest + * ; + * + * functionRest + * : attributes SimpleName typeParameters? functionParameters (":" type)? functionBody? + * ; + */ private JetNodeType parseFunction() { advance(); // TODO return FUN; } + /* + * extension + * : modifiers "extension" SimpleName? typeParameters? "for" type classBody? // properties cannot be lazy, cannot have backing fields + * ; + */ private JetNodeType parseExtension() { advance(); // TODO return EXTENSION; } + /* + * delegationSpecifier{","} + */ private void parseDelegationSpecifierList() { PsiBuilder.Marker list = mark(); while (true) { + if (at(COMMA)) { + errorAndAdvance("Expecting a delegation specifier"); + continue; + } parseDelegationSpecifier(); if (!at(COMMA)) break; advance(); // COMMA @@ -463,19 +519,37 @@ public class JetParsing { list.done(DELEGATION_SPECIFIER_LIST); } + /* + * attributes delegationSpecifier + * + * delegationSpecifier + * : constructorInvocation // type and constructor arguments + * : explicitDelegation + * ; + * + * explicitDelegation + * : userType "by" expression // TODO: Syntax is questionable + * ; + */ private void parseDelegationSpecifier() { PsiBuilder.Marker specifier = mark(); parseAttributeList(); PsiBuilder.Marker delegator = mark(); - parseTypeRef(); // TODO: Error recovery!!! + if (at(LPAR)) { + error("Expecting type name"); + } + else { + parseTypeRef(); + } + if (at(BY_KEYWORD)) { advance(); // BY_KEYWORD parseExpression(); delegator.done(DELEGATOR_BY); } else if (at(LPAR)) { - parseValueParameterList(); + parseValueArgumentList(); delegator.done(DELEGATOR_SUPER_CALL); } else { @@ -485,32 +559,6 @@ public class JetParsing { specifier.done(DELEGATION_SPECIFIER); } - private void parseValueParameterList() { - assert at(LPAR); - PsiBuilder.Marker list = mark(); - advance(); // LPAR - while (true) { - if (at(IDENTIFIER) && lookahead(1) == EQ) { - PsiBuilder.Marker named = mark(); - advance(); // IDENTIFIER - advance(); // EQ - parseExpression(); - named.done(NAMED_ARGUMENT); - } - else { - parseExpression(); - } - - if (!at(COMMA)) { - break; - } - } - - expect(RPAR, "Missing ')'"); - - list.done(VALUE_PARAMETER_LIST); - - } /* * attributes diff --git a/idea/testData/psi/BabySteps.txt b/idea/testData/psi/BabySteps.txt index 9192365ddd4..34c4173963c 100644 --- a/idea/testData/psi/BabySteps.txt +++ b/idea/testData/psi/BabySteps.txt @@ -41,7 +41,7 @@ JetFile: BabySteps.jet TYPE_REFERENCE USER_TYPE PsiElement(IDENTIFIER)('foo') - VALUE_PARAMETER_LIST + VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') NAMED_ARGUMENT PsiElement(IDENTIFIER)('d')