Passing closures outside parentheses. !!! A hack for by clause

This commit is contained in:
Andrey Breslav
2011-01-02 16:30:18 +03:00
parent 9224f75d33
commit 621a51e856
8 changed files with 351 additions and 13 deletions
+1 -1
View File
@@ -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;
+30
View File
@@ -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))
}
+262
View File
@@ -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);}