Passing closures outside parentheses. !!! A hack for by clause
This commit is contained in:
@@ -34,7 +34,7 @@ delegationSpecifier
|
||||
;
|
||||
|
||||
explicitDelegation
|
||||
: userType "by" expression // TODO: Syntax is questionable
|
||||
: userType "by" expression // internal this expression no foo {bar} is allowed // TODO: Syntax is questionable
|
||||
;
|
||||
|
||||
typeParameter
|
||||
|
||||
@@ -12,7 +12,7 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
/*package*/ class AbstractJetParsing {
|
||||
/*package*/ abstract class AbstractJetParsing {
|
||||
protected final SemanticWhitespaceAwarePsiBuilder myBuilder;
|
||||
|
||||
public AbstractJetParsing(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
@@ -227,8 +227,10 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
return myBuilder.eolInLastWhitespace() || eof();
|
||||
}
|
||||
|
||||
protected abstract JetParsing create(SemanticWhitespaceAwarePsiBuilder builder);
|
||||
|
||||
protected JetParsing createTruncatedBuilder(int eofPosition) {
|
||||
return new JetParsing(new TruncatedSemanticWhitespaceAwarePsiBuilder(myBuilder, eofPosition));
|
||||
return create(new TruncatedSemanticWhitespaceAwarePsiBuilder(myBuilder, eofPosition));
|
||||
}
|
||||
|
||||
protected class AtOffset implements TokenStreamPredicate {
|
||||
|
||||
@@ -67,7 +67,6 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
EQUALITY(EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ),
|
||||
CONJUNCTION(ANDAND),
|
||||
DISJUNCTION(OROR),
|
||||
// TODO: RHS
|
||||
MATCH(MATCH_KEYWORD) {
|
||||
@Override
|
||||
public void parseRightHandSide(JetExpressionParsing parsing) {
|
||||
@@ -185,10 +184,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
*/
|
||||
private void parsePostfixExpression() {
|
||||
// System.out.println("post at " + myBuilder.getTokenText());
|
||||
// TODO: call with a closure outside parentheses
|
||||
|
||||
PsiBuilder.Marker expression = mark();
|
||||
// parseBinaryExpression(Precedence.MEMBER_ACCESS);
|
||||
parseAtomicExpression();
|
||||
while (true) {
|
||||
if (myBuilder.eolInLastWhitespace()) {
|
||||
@@ -199,8 +196,11 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
} else if (atSet(Precedence.POSTFIX.getOperations())) {
|
||||
advance(); // operation
|
||||
expression.done(POSTFIX_EXPRESSION);
|
||||
} else if (parseCallWithClosure()) {
|
||||
expression.done(CALL_EXPRESSION);
|
||||
} else if (at(LPAR)) {
|
||||
parseValueArgumentList();
|
||||
parseCallWithClosure();
|
||||
expression.done(CALL_EXPRESSION);
|
||||
} else if (at(LT)) {
|
||||
// TODO: be (even) more clever
|
||||
@@ -212,7 +212,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
});
|
||||
if (gtPos >= 0) {
|
||||
myJetParsing.parseTypeArgumentList();
|
||||
if (at(LPAR)) parseValueArgumentList();
|
||||
if (!myBuilder.eolInLastWhitespace() && at(LPAR)) parseValueArgumentList();
|
||||
parseCallWithClosure();
|
||||
expression.done(CALL_EXPRESSION);
|
||||
} else {
|
||||
break;
|
||||
@@ -243,6 +244,17 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
expression.drop();
|
||||
}
|
||||
|
||||
/*
|
||||
* expression functionLiteral?
|
||||
*/
|
||||
protected boolean parseCallWithClosure() {
|
||||
if (!myBuilder.eolInLastWhitespace() && at(LBRACE)) {
|
||||
parseFunctionLiteral();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* atomicExpression
|
||||
* : tupleLiteral // or parenthesized expression
|
||||
@@ -384,7 +396,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
|
||||
/*
|
||||
* matchEntry
|
||||
* : attributes "case" pattern ("if" "(" expression ")")? "=>" expression SEMI? // TODO: Consider other options than "=>"
|
||||
* : attributes "case" pattern ("if" "(" expression ")")? "=>" expression SEMI?
|
||||
* ;
|
||||
*/
|
||||
private void parseMatchEntry() {
|
||||
@@ -1125,4 +1137,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
mark.done(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
return myJetParsing.create(builder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class JetParser implements PsiParser {
|
||||
@NotNull
|
||||
public ASTNode parse(IElementType iElementType, PsiBuilder psiBuilder) {
|
||||
new JetParsing(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder)).parseFile();
|
||||
JetParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder)).parseFile();
|
||||
return psiBuilder.getTreeBuilt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,32 @@ public class JetParsing extends AbstractJetParsing {
|
||||
private static final TokenSet NAMESPACE_NAME_RECOVERY_SET = TokenSet.create(DOT, EOL_OR_SEMICOLON);
|
||||
/*package*/ static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, LBRACE, LPAR);
|
||||
|
||||
private final JetExpressionParsing myExpressionParsing;
|
||||
public static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
JetParsing jetParsing = new JetParsing(builder);
|
||||
jetParsing.myExpressionParsing = new JetExpressionParsing(builder, jetParsing);
|
||||
return jetParsing;
|
||||
}
|
||||
|
||||
public JetParsing(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
public static JetParsing createForByClause(final SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
JetParsing jetParsing = new JetParsing(builder);
|
||||
jetParsing.myExpressionParsing = new JetExpressionParsing(builder, jetParsing) {
|
||||
@Override
|
||||
protected boolean parseCallWithClosure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
return createForByClause(builder);
|
||||
}
|
||||
};
|
||||
return jetParsing;
|
||||
}
|
||||
|
||||
private JetExpressionParsing myExpressionParsing;
|
||||
|
||||
private JetParsing(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
super(builder);
|
||||
this.myExpressionParsing = new JetExpressionParsing(builder, this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -979,7 +1000,8 @@ public class JetParsing extends AbstractJetParsing {
|
||||
|
||||
if (at(BY_KEYWORD)) {
|
||||
advance(); // BY_KEYWORD
|
||||
myExpressionParsing.parseExpression();
|
||||
// TODO: discuss: in nested expressions (including method bodies) one cannot use foo {bar} either, but this is required only for the top level
|
||||
createForByClause(myBuilder).myExpressionParsing.parseExpression();
|
||||
delegator.done(DELEGATOR_BY);
|
||||
}
|
||||
else if (at(LPAR)) {
|
||||
@@ -1422,6 +1444,11 @@ public class JetParsing extends AbstractJetParsing {
|
||||
parameter.done(VALUE_PARAMETER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
return createForTopLevel(builder);
|
||||
}
|
||||
|
||||
/*package*/ static class EnumDetector implements Consumer<IElementType> {
|
||||
|
||||
private boolean myEnum = false;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
fun foo() {
|
||||
f(a)
|
||||
f<foo>(a)
|
||||
f<foo>
|
||||
(a)
|
||||
f {s}
|
||||
f
|
||||
{s}
|
||||
f {
|
||||
s
|
||||
}
|
||||
f(a) {
|
||||
s
|
||||
}
|
||||
f(a)
|
||||
{
|
||||
s
|
||||
}
|
||||
f<a>(a) {
|
||||
s
|
||||
}
|
||||
f<a>(a)
|
||||
{
|
||||
s
|
||||
}
|
||||
f(foo<a, b>)
|
||||
f(foo<a, b>(a))
|
||||
f(foo<a, 1, b>(a))
|
||||
f(foo<a, (1 + 2), b>(a))
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
JetFile: FunctionCalls.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 ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
TYPE_ARGUMENT_LIST
|
||||
PsiElement(LT)('<')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
PsiElement(IDENTIFIER)('foo')
|
||||
PsiElement(GT)('>')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
TYPE_ARGUMENT_LIST
|
||||
PsiElement(LT)('<')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
PsiElement(IDENTIFIER)('foo')
|
||||
PsiElement(GT)('>')
|
||||
PsiWhiteSpace('\n ')
|
||||
TUPLE
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
PsiWhiteSpace(' ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
PsiWhiteSpace('\n ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
PsiWhiteSpace(' ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace('\n ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
TYPE_ARGUMENT_LIST
|
||||
PsiElement(LT)('<')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(GT)('>')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
CALL_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('f')
|
||||
TYPE_ARGUMENT_LIST
|
||||
PsiElement(LT)('<')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(GT)('>')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace('\n ')
|
||||
FUNCTION_LITERAL
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
BODY
|
||||
PsiElement(IDENTIFIER)('s')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(RBRACE)('}')
|
||||
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)('>')
|
||||
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)('a')
|
||||
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
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
VALUE_ARGUMENT
|
||||
BINARY_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('b')
|
||||
PsiElement(GT)('>')
|
||||
TUPLE
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
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
|
||||
TUPLE
|
||||
PsiElement(LPAR)('(')
|
||||
BINARY_EXPRESSION
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(PLUS)('+')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('2')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
VALUE_ARGUMENT
|
||||
BINARY_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('b')
|
||||
PsiElement(GT)('>')
|
||||
TUPLE
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(RBRACE)('}')
|
||||
@@ -42,6 +42,7 @@ public class JetParsingTest extends ParsingTestCase {
|
||||
public void testExtensions() throws Exception {doTest(true);}
|
||||
public void testExtensions_ERR() throws Exception {doTest(true);}
|
||||
public void testFileStart_ERR() throws Exception {doTest(true);}
|
||||
public void testFunctionCalls() throws Exception {doTest(true);}
|
||||
public void testFunctionLiterals() throws Exception {doTest(true);}
|
||||
public void testFunctionLiterals_ERR() throws Exception {doTest(true);}
|
||||
public void testFunctions() throws Exception {doTest(true);}
|
||||
|
||||
Reference in New Issue
Block a user