From 48180072914f26d3509e6adafd53ec635e1673f0 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 8 Feb 2011 20:21:11 +0300 Subject: [PATCH] New syntax fro patterns --- grammar/src/expressions.grm | 10 ++-- grammar/src/when.grm | 20 +++---- idea/src/org/jetbrains/jet/JetNodeTypes.java | 1 + .../lang/parsing/JetExpressionParsing.java | 44 +++++++------- idea/testData/psi/AttributesOnPatterns.jet | 4 +- idea/testData/psi/AttributesOnPatterns.txt | 60 +++++++++++++++++-- idea/testData/psi/When.jet | 20 +++---- 7 files changed, 105 insertions(+), 54 deletions(-) diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm index 9f4151f48ee..ce251fa5230 100644 --- a/grammar/src/expressions.grm +++ b/grammar/src/expressions.grm @@ -43,12 +43,12 @@ comparison ; namedInfixOrTypeExpression - : elvisOperation (inOperation elvisOperation)* - : elvisOperation (isOperation isRHS)? - : elvisOperation (typeOperation type)? + : elvisExpression (inOperation elvisExpression)* + : elvisExpression (isOperation isRHS)? + : elvisExpression (typeOperation type)? ; -elvisOperation +elvisExpression : infixFunctionCall ("?:" infixFunctionCall)* ; @@ -170,7 +170,7 @@ postfixUnaryOperation : typeArguments? valueArguments : typeArguments : arrayAccess - : memberAccessOperation atomicExpression + : memberAccessOperation postfixUnaryOperation // TODO: Review ; memberAccessOperation diff --git a/grammar/src/when.grm b/grammar/src/when.grm index fb90a99d0a6..f15abf5b4ac 100644 --- a/grammar/src/when.grm +++ b/grammar/src/when.grm @@ -15,6 +15,7 @@ whenConditionIf whenCondition : expression +// : "." atomicExpression typeArguments? valueArguments? : ("in" | "!in") expression : ("is" | "!is") isRHS ; @@ -22,17 +23,18 @@ whenCondition pattern : attributes pattern : type // '[a] T' is a type-pattern 'T' with an attribute '[a]', not a type-pattern '[a] T' - // this makes sense because is-chack may be different for a type with attributes + // this makes sense because is-check may be different for a type with attributes : tuplePattern : decomposerPattern : constantPattern : bindingPattern - : expressionPattern + : "*" // wildcard pattern ; decomposerPattern : type - : qualifiedName typeParameters? (tuplePattern)? +// TODO : typeParameters will be consumed by the expression + : elvisExpression typeParameters? '@' tuplePattern ; constantPattern @@ -44,7 +46,7 @@ tuplePattern ; bindingPattern - : "?" SimpleName? binding? + : "val" SimpleName binding? ; binding @@ -52,13 +54,5 @@ binding : "!is" pattern : "in" expression : "!in" expression - : "=" expression - ; - -qualifiedName - : ("namespace" ".")? SimpleName{","} - ; - -expressionPattern - : "=" expression + : ":" type ; \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index 37c733d9e72..7341bd4c811 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -114,6 +114,7 @@ public interface JetNodeTypes { JetNodeType TYPE_PATTERN = new JetNodeType("TYPE_PATTERN"); JetNodeType EXPRESSION_PATTERN = new JetNodeType("EXPRESSION_PATTERN"); JetNodeType BINDING_PATTERN = new JetNodeType("BINDING_PATTERN"); + JetNodeType WILDCARD_PATTERN = new JetNodeType("WILDCARD_PATTERN"); JetNodeType WHEN = new JetNodeType("WHEN", JetWhenExpression.class); JetNodeType WHEN_ENTRY = new JetNodeType("WHEN_ENTRY", JetWhenEntry.class); JetNodeType WHEN_CONDITION = new JetNodeType("WHEN_CONDITION"); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 5e072a32b08..ba3d09fcbd1 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -171,7 +171,6 @@ public class JetExpressionParsing extends AbstractJetParsing { } private final JetParsing myJetParsing; - private TokenSet expressionFollow = null; private TokenSet decomposerExpressionFollow = null; public JetExpressionParsing(SemanticWhitespaceAwarePsiBuilder builder, JetParsing jetParsing) { @@ -181,16 +180,19 @@ public class JetExpressionParsing extends AbstractJetParsing { private TokenSet getDecomposerExpressionFollow() { // TODO : memoize - List elvisFollow = new ArrayList(); - Precedence precedence = Precedence.ELVIS; - while (precedence != null) { - IElementType[] types = precedence.getOperations().getTypes(); - for (IElementType type : types) { - elvisFollow.add(type); + if (decomposerExpressionFollow == null) { + List elvisFollow = new ArrayList(); + Precedence precedence = Precedence.ELVIS; + while (precedence != null) { + IElementType[] types = precedence.getOperations().getTypes(); + for (IElementType type : types) { + elvisFollow.add(type); + } + precedence = precedence.higher; } - precedence = precedence.higher; + decomposerExpressionFollow = TokenSet.orSet(EXPRESSION_FOLLOW, TokenSet.create(elvisFollow.toArray(new IElementType[elvisFollow.size()]))); } - return TokenSet.orSet(EXPRESSION_FOLLOW, TokenSet.create(elvisFollow.toArray(new IElementType[elvisFollow.size()]))); + return decomposerExpressionFollow; } /* @@ -690,13 +692,12 @@ public class JetExpressionParsing extends AbstractJetParsing { parseTuplePattern(TUPLE_PATTERN_ENTRY); pattern.done(TUPLE_PATTERN); } - else if (at(QUEST)) { + else if (at(MUL)) { + advance(); // MUL + pattern.done(WILDCARD_PATTERN); + } else if (at(VAL_KEYWORD)) { parseBindingPattern(); pattern.done(BINDING_PATTERN); - } else if (at(EQ)) { - advance(); // EQ - parseExpression(); - pattern.done(EXPRESSION_PATTERN); } else if (parseLiteralConstant()) { pattern.done(EXPRESSION_PATTERN); } else { @@ -741,7 +742,7 @@ public class JetExpressionParsing extends AbstractJetParsing { /* * bindingPattern - * : "?" SimpleName? binding? + * : "val" SimpleName binding? * ; * * binding @@ -749,15 +750,15 @@ public class JetExpressionParsing extends AbstractJetParsing { * : "!is" pattern * : "in" expression * : "!in" expression - * : "=" expression + * : ":" type * ; */ private void parseBindingPattern() { - assert _at(QUEST); + assert _at(VAL_KEYWORD); - advance(); // QUEST + advance(); // VAL_KEYWORD - consumeIf(IDENTIFIER); + expect(IDENTIFIER, "Expecting an identifier"); if (at(IS_KEYWORD) || at(NOT_IS)) { advance(); // IS_KEYWORD or NOT_IS @@ -767,12 +768,13 @@ public class JetExpressionParsing extends AbstractJetParsing { advance(); // IN_KEYWORD ot NOT_IN parseExpression(); - } else if (at(EQ)) { + } else if (at(COLON)) { advance(); // EQ - parseExpression(); + myJetParsing.parseTypeRef(); } } + /* * arrayAccess * : "[" expression{","} "]" diff --git a/idea/testData/psi/AttributesOnPatterns.jet b/idea/testData/psi/AttributesOnPatterns.jet index 56cc9f90eec..ec9ead0312a 100644 --- a/idea/testData/psi/AttributesOnPatterns.jet +++ b/idea/testData/psi/AttributesOnPatterns.jet @@ -1,7 +1,9 @@ fun foo() { when (e) { - is [a] =2 => d + is [a] val a => d + is [a] val a is foo => d + is [a] * => d is [a] 2 => d is [a] T => d is [a] T @ () => d diff --git a/idea/testData/psi/AttributesOnPatterns.txt b/idea/testData/psi/AttributesOnPatterns.txt index ca8d784b9ba..51a419457c5 100644 --- a/idea/testData/psi/AttributesOnPatterns.txt +++ b/idea/testData/psi/AttributesOnPatterns.txt @@ -27,7 +27,7 @@ JetFile: AttributesOnPatterns.jet WHEN_CONDITION PsiElement(is)('is') PsiWhiteSpace(' ') - EXPRESSION_PATTERN + BINDING_PATTERN ATTRIBUTE_ANNOTATION PsiElement(LBRACKET)('[') ATTRIBUTE @@ -37,9 +37,61 @@ JetFile: AttributesOnPatterns.jet PsiElement(IDENTIFIER)('a') PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') - PsiElement(EQ)('=') - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('2') + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(DOUBLE_ARROW)('=>') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('d') + PsiWhiteSpace('\n ') + WHEN_ENTRY + WHEN_CONDITION + PsiElement(is)('is') + PsiWhiteSpace(' ') + BINDING_PATTERN + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(is)('is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(DOUBLE_ARROW)('=>') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('d') + PsiWhiteSpace('\n ') + WHEN_ENTRY + WHEN_CONDITION + PsiElement(is)('is') + PsiWhiteSpace(' ') + WILDCARD_PATTERN + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + PsiElement(MUL)('*') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') diff --git a/idea/testData/psi/When.jet b/idea/testData/psi/When.jet index 264b41627e7..f3b1ab6590c 100644 --- a/idea/testData/psi/When.jet +++ b/idea/testData/psi/When.jet @@ -26,10 +26,9 @@ fun foo() { is 'c' => foo is "sadfsa" => foo is """ddd""" => foo - is ? => foo - is ? is Foo => foo - is ?a is Foo => foo - is (?a is Foo, b) => foo + is * => foo + is val a is Foo => foo + is (val a is Foo, b) => foo } when (when(when (e) { @@ -43,21 +42,22 @@ fun foo() { fun foo() { when (val a = e) { is Tree => c - is Tree @ (null, ?r) => c + is Tree @ (null, val r) => c is a @ (a, b) => c is a @ (a, b) => c is a.a @ (a, b) => c is a.a @ (foo = a, bar = b) => c is namespace.a.a @ (a, b) => c - is a @ (?a is T, b) => c + is a @ (val a is T, b) => c is a @ (b, 1) => c in 1..2 => dsf !in 2 => sd !is t => d is {(foo) : Bar} => fgpp - is (1, ?a is Foo, ?, ? is Foo, bar) => d - is (Foo, ?a in 1..2, ?, ? !is Foo, ?bar = foo.bar(a)) => d + is (1, val a is Foo, *, Foo, bar) => d + is (Foo, val a in 1..2, *, val _ !is Foo, val bar is foo.bar @ (a)) => d is (Int, Int) => 2 + is val a : Foo => 2 else => foo else continue } @@ -66,11 +66,11 @@ fun foo() { fun foo() { when (val a = e) { is Tree, - is Tree @ (null, ?r), + is Tree @ (null, val r), is a @ (a, b) => c 1, foo(), bar, 2 + 3, is a @ (a, b) => c - is a.a @ (=a + 3, b) => c + is a.a @ (val b, b) if (b == a + 3) => c } }