Graet Syntactic Shift : Syntax for function literals fixed

This commit is contained in:
Andrey Breslav
2011-12-21 10:52:58 +02:00
parent 6aad3b2662
commit 6bad4830c3
10 changed files with 234 additions and 86 deletions
@@ -1082,83 +1082,112 @@ public class JetExpressionParsing extends AbstractJetParsing {
myBuilder.enableNewlines();
advance(); // LBRACE
int doubleArrowPos = matchTokenStreamPredicate(new FirstBefore(new At(ARROW), new At(RBRACE)) {
@Override
public boolean isTopLevel(int openAngleBrackets, int openBrackets, int openBraces, int openParentheses) {
return openBraces == 0;
boolean paramsFound = false;
if (at(ARROW)) {
// { -> ...}
advance(); // ARROW
mark().done(VALUE_PARAMETER_LIST);
paramsFound = true;
}
else if (at(LPAR)) {
// Look for ARROW after matching RPAR
// {(a, b) -> ...}
{
PsiBuilder.Marker rollbackMarker = mark();
parseFunctionLiteralParametersAndType();
paramsFound = rollbackOrDropAt(rollbackMarker, ARROW);
}
});
boolean doubleArrowPresent = doubleArrowPos >= 0;
if (doubleArrowPresent) {
boolean dontExpectParameters = false;
int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtOffset(doubleArrowPos)));
if (lastDot >= 0) { // There is a receiver type
createTruncatedBuilder(lastDot).parseTypeRef();
expect(DOT, "Expecting '.'");
if (!at(LPAR)) {
int firstLParPos = matchTokenStreamPredicate(new FirstBefore(new At(LPAR), new AtOffset(doubleArrowPos)));
if (firstLParPos >= 0) {
errorUntilOffset("Expecting '('", firstLParPos);
} else {
errorUntilOffset("To specify a receiver type, use the full notation: {ReceiverType.(parameters) [: ReturnType] => ...}",
doubleArrowPos);
dontExpectParameters = true;
if (!paramsFound) {
// If not found, try a typeRef DOT and then LPAR .. RPAR ARROW
// {((A) -> B).(x) -> ... }
PsiBuilder.Marker rollbackMarker = mark();
int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RPAR)));
if (lastDot >= 0) {
createTruncatedBuilder(lastDot).parseTypeRef();
if (at(DOT)) {
advance(); // DOT
parseFunctionLiteralParametersAndType();
}
}
paramsFound = rollbackOrDropAt(rollbackMarker, ARROW);
}
if (at(LPAR)) {
parseFunctionLiteralParameterList();
if (at(COLON)) {
advance(); // COLON
if (at(ARROW)) {
error("Expecting a type");
}
else {
myJetParsing.parseTypeRef();
}
}
}
else if (!dontExpectParameters) {
PsiBuilder.Marker parameterList = mark();
while (!eof()) {
PsiBuilder.Marker parameter = mark();
int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW));
parameter.done(VALUE_PARAMETER);
if (at(COLON)) {
errorUntilOffset("To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType => ...}", doubleArrowPos);
}
else if (at(ARROW)) {
break;
}
else if (!at(COMMA)) {
errorUntilOffset("Expecting '=>' or ','", doubleArrowPos);
}
else {
advance(); // COMMA
}
}
parameterList.done(VALUE_PARAMETER_LIST);
}
expectNoAdvance(ARROW, "Expecting '=>'");
}
else {
if (at(IDENTIFIER)) {
// Try to parse a simple name list followed by an ARROW
// {a -> ...}
// {a, b -> ...}
PsiBuilder.Marker rollbackMarker = mark();
parseFunctionLiteralShorthandParameterList();
parseOptionalFunctionLiteralType();
paramsFound = rollbackOrDropAt(rollbackMarker, ARROW);
}
if (!paramsFound && atSet(JetParsing.TYPE_REF_FIRST)) {
// Try to parse a type DOT valueParameterList ARROW
// {A.(b) -> ...}
PsiBuilder.Marker rollbackMarker = mark();
int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RBRACE)));
if (lastDot >= 0) { // There is a receiver type
createTruncatedBuilder(lastDot).parseTypeRef();
}
if (at(DOT)) {
advance(); // DOT
parseFunctionLiteralParametersAndType();
paramsFound = rollbackOrDropAt(rollbackMarker, ARROW);
}
else {
rollbackMarker.rollbackTo();
}
}
// int doubleArrowPos = matchTokenStreamPredicate(new FirstBefore(new At(ARROW), new At(RBRACE)) {
// @Override
// public boolean isTopLevel(int openAngleBrackets, int openBrackets, int openBraces, int openParentheses) {
// return openBraces == 0;
// }
// });
//
// boolean doubleArrowPresent = doubleArrowPos >= 0;
// if (doubleArrowPresent) {
// boolean dontExpectParameters = false;
//
// int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtOffset(doubleArrowPos)));
// if (lastDot >= 0) { // There is a receiver type
// createTruncatedBuilder(lastDot).parseTypeRef();
//
// expect(DOT, "Expecting '.'");
//
// if (!at(LPAR)) {
// int firstLParPos = matchTokenStreamPredicate(new FirstBefore(new At(LPAR), new AtOffset(doubleArrowPos)));
//
// if (firstLParPos >= 0) {
// errorUntilOffset("Expecting '('", firstLParPos);
// } else {
// errorUntilOffset("To specify a receiver type, use the full notation: {ReceiverType.(parameters) [: ReturnType] => ...}",
// doubleArrowPos);
// dontExpectParameters = true;
// }
// }
//
// }
//
// if (at(LPAR)) {
// parseFunctionLiteralParametersAndType();
// }
// else if (!dontExpectParameters) {
// parseFunctionLiteralShorthandParameterList();
// }
//
// expectNoAdvance(ARROW, "Expecting '=>'");
// }
}
if (!paramsFound) {
if (preferBlock) {
literal.drop();
parseStatements();
@@ -1180,6 +1209,74 @@ public class JetExpressionParsing extends AbstractJetParsing {
literalExpression.done(FUNCTION_LITERAL_EXPRESSION);
}
private boolean rollbackOrDropAt(PsiBuilder.Marker rollbackMarker, IElementType dropAt) {
if (at(dropAt)) {
advance(); // dropAt
rollbackMarker.drop();
return true;
}
rollbackMarker.rollbackTo();
return false;
}
/*
* SimpleName{,}
*/
private void parseFunctionLiteralShorthandParameterList() {
PsiBuilder.Marker parameterList = mark();
while (!eof()) {
PsiBuilder.Marker parameter = mark();
// int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
// createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW));
parameter.done(VALUE_PARAMETER);
if (at(COLON)) {
PsiBuilder.Marker errorMarker = mark();
advance(); // COLON
myJetParsing.parseTypeRef();
errorMarker.error("To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType => ...}");
}
else if (at(ARROW)) {
break;
}
else if (at(COMMA)) {
advance(); // COMMA
}
else {
error("Expecting '->' or ','");
break;
}
}
parameterList.done(VALUE_PARAMETER_LIST);
}
private void parseFunctionLiteralParametersAndType() {
parseFunctionLiteralParameterList();
parseOptionalFunctionLiteralType();
}
/*
* (":" type)?
*/
private void parseOptionalFunctionLiteralType() {
if (at(COLON)) {
advance(); // COLON
if (at(ARROW)) {
error("Expecting a type");
}
else {
myJetParsing.parseTypeRef();
}
}
}
/*
* "(" (modifiers SimpleName (":" type)?){","} ")"
*/
@@ -1354,7 +1354,13 @@ public class JetParsing extends AbstractJetParsing {
typeRefMarker.done(TYPE_REFERENCE);
advance(); // DOT
parseFunctionTypeContents().drop();
if (at(LPAR)) {
parseFunctionTypeContents().drop();
}
else {
error("Expecting function type");
}
typeRefMarker = precede.precede();
precede.done(FUNCTION_TYPE);
@@ -1519,8 +1525,9 @@ public class JetParsing extends AbstractJetParsing {
}
private PsiBuilder.Marker parseFunctionTypeContents() {
assert _at(LPAR) : tt();
//
// assert _at(LPAR) : tt();
if (!_at(LPAR))
System.out.println(myBuilder.getTokenText());
PsiBuilder.Marker functionType = mark();
// advance(); // LPAR
@@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
@@ -173,7 +174,8 @@ public class TypeResolver {
@Override
public void visitJetElement(JetElement element) {
throw new IllegalArgumentException("Unsupported type: " + element);
trace.report(UNSUPPORTED.on(element, "Self-types are not supported yet"));
// throw new IllegalArgumentException("Unsupported type: " + element);
}
});
}
+8 -8
View File
@@ -121,17 +121,17 @@ sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== flfun ==
fun flfun(f : fun () : Any) : Unit {}
fun flfun(f : () -> Any) : Unit {}
---------------------
l0:
<START> NEXT:[v(f : fun () : Any)] PREV:[]
v(f : fun () : Any) NEXT:[w(f)] PREV:[<START>]
w(f) NEXT:[read (Unit)] PREV:[v(f : fun () : Any)]
read (Unit) NEXT:[<END>] PREV:[w(f)]
<START> NEXT:[v(f : () -> Any)] PREV:[]
v(f : () -> Any) NEXT:[w(f)] PREV:[<START>]
w(f) NEXT:[read (Unit)] PREV:[v(f : () -> Any)]
read (Unit) NEXT:[<END>] PREV:[w(f)]
l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)]
<END> NEXT:[<SINK>] PREV:[read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
<SINK> NEXT:[] PREV:[<END>]
=====================
+1 -1
View File
@@ -20,4 +20,4 @@ fun foo(a : Boolean, b : Int) : Unit {}
fun genfun<T>() : Unit {}
fun flfun(f : fun () : Any) : Unit {}
fun flfun(f : () -> Any) : Unit {}
@@ -0,0 +1,43 @@
class Foo
class Bar
fun a(vararg a : Any) = a
fun test() {
a(1
, {}
, { -> 1}
, {1}
, {x}
, {-> 1}
, {x -> 1}
, {x, y -> 1}
, {(x, y) -> 1}
, {(x, y) : Int -> 1}
, {(x) -> 1}
, {(x) : Int -> 1}
, {(x)}
, {(x).(y)}
, {x.(y)}
, {Int.(x) -> 1}
, {A.B.(x) -> 1}
, {A.B.(x, y) -> 1}
, {Int.(x) : Int -> 1}
, {Int.(x, y) -> 1}
, {Int.(x, y) : Int -> 1}
, {(Int).(x, y) -> 1}
, {(Int).(x, y) : Int -> 1}
, {(Int).(x, y) : (Int) -> Int -> {1}}
, {Int? .(x, y) -> 1}
, {This.(x, y) -> 1}
, {#(A, B).(x, y) -> 1}
, {#(a, b).(y)}
, {#(a, b)}
, {Foo<Bar>.x}
, {Foo<Bar>.(x)}
, {Foo<Bar>.(x) -> x}
, {Foo.Bar.Baz.(x) -> x}
, {Foo<Bar>.(x) : Int -> x}
, {Foo.Bar.Baz.(x) : Int -> x}
)
}
@@ -48,7 +48,7 @@ public abstract class JetTestCaseBuilder {
}
public static void appendTestsInDirectory(String baseDataDir, String dataPath, boolean recursive, final FilenameFilter filter, NamedTestFactory factory, TestSuite suite) {
final String extensionJet = ".jet.jet";
final String extensionJet = ".jet";
final String extensionKt = ".kt";
final FilenameFilter extensionFilter = new FilenameFilter() {
@Override
@@ -10,7 +10,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.lang.Configuration;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.JetDeclaration;
@@ -85,7 +84,7 @@ public class JetDiagnosticsTest extends JetLiteFixture {
@Override
public void runTest() throws Exception {
String testFileName = name + ".kt";
String testFileName = name + ".jet";
String expectedText = loadFile(testFileName);
@@ -86,7 +86,7 @@ public class PatternMatchingTest extends CodegenTestCase {
}
public void testTuplePattern() throws Exception {
loadText("fun foo(x: (Any, Any)) = when(x) { is #(1,2) -> \"one,two\"; else -> \"something\" }");
loadText("fun foo(x: #(Any, Any)) = when(x) { is #(1,2) -> \"one,two\"; else -> \"something\" }");
Method foo = generateFunction();
final Object result;
try {