diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm
index aa51044370b..a9effdbb696 100644
--- a/grammar/src/expressions.grm
+++ b/grammar/src/expressions.grm
@@ -58,7 +58,7 @@ elvisOperation
// ATTENTION
infixFunctionCall
- : rangeExpression (SimpleName (typeParameters | rangeExpression))*
+ : rangeExpression (SimpleName (typeArguments | rangeExpression))*
;
rangeExpression
@@ -168,7 +168,7 @@ prefixUnaryOperation
postfixUnaryOperation
: "++" : "--"
: typeArguments? valueArguments
- : typeArguments
+ // : typeArguments // TODO:
: arrayAccess
;
diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
index 4cd5a1cc3d8..5231a6de9b8 100644
--- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
+++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
@@ -14,6 +14,17 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
*/
public class JetExpressionParsing extends AbstractJetParsing {
private final JetParsing myJetParsing;
+ private static final TokenSet TYPE_ARGUMENT_LIST_STOPPERS = TokenSet.create(
+ INTEGER_LITERAL, LONG_LITERAL, FLOAT_LITERAL, CHARACTER_LITERAL, STRING_LITERAL, RAW_STRING_LITERAL,
+ NAMESPACE_KEYWORD, AS_KEYWORD, TYPE_KEYWORD, CLASS_KEYWORD, THIS_KEYWORD, VAL_KEYWORD, VAR_KEYWORD,
+ FUN_KEYWORD, DECOMPOSER_KEYWORD, EXTENSION_KEYWORD, FOR_KEYWORD, NULL_KEYWORD, TYPEOF_KEYWORD,
+ NEW_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD,
+ CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD, TRY_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD,
+ MATCH_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS, MUL, PLUS, MINUS, EXCL, DIV, PERC, LTEQ,
+ // TODO GTEQ,
+ EQEQEQ, ARROW, DOUBLE_ARROW, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, SAFE_ACCESS, ELVIS, QUEST,
+ SEMICOLON, RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ, NOT_IN, NOT_IS, HASH, EOL_OR_SEMICOLON
+ );
public JetExpressionParsing(SemanticWhitespaceAwarePsiBuilder builder, JetParsing jetParsing) {
super(builder);
@@ -29,7 +40,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
},
- POSTFIX(PLUSPLUS, MINUSMINUS), // valueArguments : arrayAccess
+ POSTFIX(PLUSPLUS, MINUSMINUS), // typeArguments? valueArguments : arrayAccess
PREFIX(MINUS, PLUS, MINUSMINUS, PLUSPLUS, EXCL) { // attributes
@@ -173,6 +184,22 @@ public class JetExpressionParsing extends AbstractJetParsing {
} else if (at(LPAR)) {
parseValueArgumentList();
expression.done(CALL_EXPRESSION);
+ } else if (at(LT)) {
+ // TODO: be more clever: f(foo(c)) is not a function call
+ int gtPos = matchTokenStreamPredicate(new FirstBefore(new At(GT), new AtSet(TYPE_ARGUMENT_LIST_STOPPERS, false)) {
+ @Override
+ public boolean isTopLevel(int openAngleBrackets, int openBrackets, int openBraces, int openParentheses) {
+ return openAngleBrackets == 1 && openBrackets == 0 && openBraces == 0 && openParentheses == 0;
+ }
+ });
+ if (gtPos >= 0) {
+ myJetParsing.parseTypeArgumentList();
+// if (at(LPAR)) parseValueArgumentList(); TODO : we can do this...
+ parseValueArgumentList();
+ expression.done(CALL_EXPRESSION);
+ } else {
+ expression.drop();
+ }
} else {
expression.drop();
}
diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java
index 77eb34b705d..4483567250f 100644
--- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java
+++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java
@@ -1215,7 +1215,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* (optionalProjection type){","}
*/
- private void parseTypeArgumentList() {
+ public void parseTypeArgumentList() {
if (!at(LT)) return;
PsiBuilder.Marker list = mark();
diff --git a/idea/testData/psi/Precedence.jet b/idea/testData/psi/Precedence.jet
index 50d46e09699..e62234233f2 100644
--- a/idea/testData/psi/Precedence.jet
+++ b/idea/testData/psi/Precedence.jet
@@ -1,4 +1,8 @@
fun foo() {
+ f(foo(x)))
+ f(foo(x))
+ f((foo(x))
+ f(foo')
+ TUPLE
+ PsiElement(LPAR)('(')
+ PsiElement(IDENTIFIER)('x')
+ PsiElement(RPAR)(')')
+ PsiElement(RPAR)(')')
+ PsiElement(RPAR)(')')
+ PsiWhiteSpace('\n ')
+ CALL_EXPRESSION
+ PsiElement(IDENTIFIER)('f')
+ VALUE_ARGUMENT_LIST
+ PsiElement(LPAR)('(')
+ VALUE_ARGUMENT
+ CALL_EXPRESSION
+ PsiElement(IDENTIFIER)('foo')
+ TYPE_ARGUMENT_LIST
+ PsiElement(LT)('<')
+ TYPE_REFERENCE
+ USER_TYPE
+ PsiElement(IDENTIFIER)('a')
+ PsiElement(COMMA)(',')
+ PsiWhiteSpace(' ')
+ TYPE_REFERENCE
+ USER_TYPE
+ PsiElement(IDENTIFIER)('b')
+ PsiElement(GT)('>')
+ VALUE_ARGUMENT_LIST
+ PsiElement(LPAR)('(')
+ VALUE_ARGUMENT
+ PsiElement(IDENTIFIER)('x')
+ PsiElement(RPAR)(')')
+ PsiElement(RPAR)(')')
+ PsiWhiteSpace('\n ')
+ CALL_EXPRESSION
+ PsiElement(IDENTIFIER)('f')
+ VALUE_ARGUMENT_LIST
+ PsiElement(LPAR)('(')
+ VALUE_ARGUMENT
+ TUPLE
+ PsiElement(LPAR)('(')
+ BINARY_EXPRESSION
+ PsiElement(IDENTIFIER)('foo')
+ PsiElement(LT)('<')
+ PsiElement(IDENTIFIER)('a')
+ PsiElement(RPAR)(')')
+ PsiElement(COMMA)(',')
+ PsiWhiteSpace(' ')
+ VALUE_ARGUMENT
+ BINARY_EXPRESSION
+ PsiElement(IDENTIFIER)('b')
+ PsiElement(GT)('>')
+ TUPLE
+ PsiElement(LPAR)('(')
+ PsiElement(IDENTIFIER)('x')
+ PsiElement(RPAR)(')')
+ PsiElement(RPAR)(')')
+ PsiWhiteSpace('\n ')
+ CALL_EXPRESSION
+ PsiElement(IDENTIFIER)('f')
+ VALUE_ARGUMENT_LIST
+ PsiElement(LPAR)('(')
+ VALUE_ARGUMENT
+ BINARY_EXPRESSION
+ PsiElement(IDENTIFIER)('foo')
+ PsiElement(LT)('<')
+ PsiElement(IDENTIFIER)('a')
+ PsiElement(COMMA)(',')
+ PsiWhiteSpace(' ')
+ VALUE_ARGUMENT
+ PsiElement(IDENTIFIER)('b')
+ PsiElement(RPAR)(')')
+ PsiWhiteSpace('\n ')
BINARY_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')