Improve parser recovery for list of value parameters/arguments

This commit is contained in:
Alexey Sedunov
2013-05-31 19:32:21 +04:00
parent a2ee65e64c
commit 3a2e30152a
7 changed files with 176 additions and 85 deletions
@@ -53,7 +53,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_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, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD, TRY_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD,
WHEN_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS, EXCLEXCL, WHEN_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS, EXCLEXCL,
// MUL, // MUL,
PLUS, MINUS, EXCL, DIV, PERC, LTEQ, PLUS, MINUS, EXCL, DIV, PERC, LTEQ,
// TODO GTEQ, foo<bar, baz>=x // TODO GTEQ, foo<bar, baz>=x
EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, SAFE_ACCESS, ELVIS, EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, SAFE_ACCESS, ELVIS,
@@ -111,17 +111,17 @@ public class JetExpressionParsing extends AbstractJetParsing {
); );
private static final TokenSet STATEMENT_FIRST = TokenSet.orSet( private static final TokenSet STATEMENT_FIRST = TokenSet.orSet(
EXPRESSION_FIRST, EXPRESSION_FIRST,
TokenSet.create( TokenSet.create(
// declaration // declaration
LBRACKET, // attribute LBRACKET, // attribute
FUN_KEYWORD, FUN_KEYWORD,
VAL_KEYWORD, VAR_KEYWORD, VAL_KEYWORD, VAR_KEYWORD,
TRAIT_KEYWORD, TRAIT_KEYWORD,
CLASS_KEYWORD, CLASS_KEYWORD,
TYPE_KEYWORD TYPE_KEYWORD
), ),
MODIFIER_KEYWORDS MODIFIER_KEYWORDS
); );
/*package*/ static final TokenSet EXPRESSION_FOLLOW = TokenSet.create( /*package*/ static final TokenSet EXPRESSION_FOLLOW = TokenSet.create(
@@ -174,7 +174,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
EQUALITY(EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ), EQUALITY(EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ),
CONJUNCTION(ANDAND), CONJUNCTION(ANDAND),
DISJUNCTION(OROR), DISJUNCTION(OROR),
// ARROW(JetTokens.ARROW), // ARROW(JetTokens.ARROW),
ASSIGNMENT(EQ, PLUSEQ, MINUSEQ, MULTEQ, DIVEQ, PERCEQ), ASSIGNMENT(EQ, PLUSEQ, MINUSEQ, MULTEQ, DIVEQ, PERCEQ),
; ;
@@ -287,7 +287,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
* see the precedence table * see the precedence table
*/ */
private void parseBinaryExpression(Precedence precedence) { private void parseBinaryExpression(Precedence precedence) {
// System.out.println(precedence.name() + " at " + myBuilder.getTokenText()); // System.out.println(precedence.name() + " at " + myBuilder.getTokenText());
PsiBuilder.Marker expression = mark(); PsiBuilder.Marker expression = mark();
@@ -300,7 +300,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
JetNodeType resultType = precedence.parseRightHandSide(operation, this); JetNodeType resultType = precedence.parseRightHandSide(operation, this);
expression.done(resultType); expression.done(resultType);
expression = expression.precede(); expression = expression.precede();
} }
expression.drop(); expression.drop();
@@ -310,7 +310,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
* operation? prefixExpression * operation? prefixExpression
*/ */
private void parsePrefixExpression() { private void parsePrefixExpression() {
// System.out.println("pre at " + myBuilder.getTokenText()); // System.out.println("pre at " + myBuilder.getTokenText());
if (at(LBRACKET)) { if (at(LBRACKET)) {
if (!parseLocalDeclaration()) { if (!parseLocalDeclaration()) {
@@ -485,10 +485,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
*/ */
protected boolean parseCallWithClosure() { protected boolean parseCallWithClosure() {
boolean success = false; boolean success = false;
// while (!myBuilder.newlineBeforeCurrentToken() // while (!myBuilder.newlineBeforeCurrentToken()
// && (at(LBRACE) // && (at(LBRACE)
while ((at(LBRACE) while ((at(LBRACE)
|| atSet(LABELS) && lookahead(1) == LBRACE)) { || atSet(LABELS) && lookahead(1) == LBRACE)) {
if (!at(LBRACE)) { if (!at(LBRACE)) {
assert _atSet(LABELS); assert _atSet(LABELS);
parsePrefixExpression(); parsePrefixExpression();
@@ -520,7 +520,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
* ; * ;
*/ */
private void parseAtomicExpression() { private void parseAtomicExpression() {
// System.out.println("atom at " + myBuilder.getTokenText()); // System.out.println("atom at " + myBuilder.getTokenText());
if (at(LPAR)) { if (at(LPAR)) {
parseParenthesizedExpression(); parseParenthesizedExpression();
@@ -574,7 +574,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseDoWhile(); parseDoWhile();
} }
else if (atSet(CLASS_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, else if (atSet(CLASS_KEYWORD, FUN_KEYWORD, VAL_KEYWORD,
VAR_KEYWORD, TYPE_KEYWORD)) { VAR_KEYWORD, TYPE_KEYWORD)) {
parseLocalDeclaration(); parseLocalDeclaration();
} }
else if (at(FIELD_IDENTIFIER)) { else if (at(FIELD_IDENTIFIER)) {
@@ -784,7 +784,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
if (!at(ARROW)) { if (!at(ARROW)) {
errorUntil("Expecting '->'", TokenSet.create(ARROW, errorUntil("Expecting '->'", TokenSet.create(ARROW,
RBRACE, EOL_OR_SEMICOLON)); RBRACE, EOL_OR_SEMICOLON));
} }
if (at(ARROW)) { if (at(ARROW)) {
@@ -798,7 +798,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
} }
} }
else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) { else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) {
errorAndAdvance("Expecting '->'"); errorAndAdvance("Expecting '->'");
} }
} }
else { else {
@@ -982,8 +982,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseFunctionLiteralParametersAndType(); parseFunctionLiteralParametersAndType();
paramsFound = preferParamsToExpressions ? paramsFound = preferParamsToExpressions ?
rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
rollbackOrDropAt(rollbackMarker, ARROW); rollbackOrDropAt(rollbackMarker, ARROW);
} }
if (!paramsFound) { if (!paramsFound) {
@@ -1047,8 +1047,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
} }
private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker, private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker,
JetToken expected, String expectMessage, JetToken expected, String expectMessage,
IElementType validForDrop) { IElementType validForDrop) {
if (at(expected)) { if (at(expected)) {
advance(); // dropAt advance(); // dropAt
rollbackMarker.drop(); rollbackMarker.drop();
@@ -1074,8 +1074,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
while (!eof()) { while (!eof()) {
PsiBuilder.Marker parameter = mark(); PsiBuilder.Marker parameter = mark();
// int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos))); // int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
// createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false); // createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW)); expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW));
@@ -1135,8 +1135,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
} }
return preferParamsToExpressions ? return preferParamsToExpressions ?
rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
rollbackOrDropAt(rollbackMarker, ARROW); rollbackOrDropAt(rollbackMarker, ARROW);
} }
private void parseFunctionLiteralParametersAndType() { private void parseFunctionLiteralParametersAndType() {
@@ -1252,38 +1252,38 @@ public class JetExpressionParsing extends AbstractJetParsing {
* ; * ;
*/ */
private IElementType parseLocalDeclarationRest(boolean isEnum) { private IElementType parseLocalDeclarationRest(boolean isEnum) {
IElementType keywordToken = tt(); IElementType keywordToken = tt();
IElementType declType = null; IElementType declType = null;
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) { if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) {
declType = myJetParsing.parseClass(isEnum); declType = myJetParsing.parseClass(isEnum);
} }
else if (keywordToken == FUN_KEYWORD) { else if (keywordToken == FUN_KEYWORD) {
declType = myJetParsing.parseFunction(); declType = myJetParsing.parseFunction();
} }
else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) { else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
declType = myJetParsing.parseProperty(true); declType = myJetParsing.parseProperty(true);
} }
else if (keywordToken == TYPE_KEYWORD) { else if (keywordToken == TYPE_KEYWORD) {
declType = myJetParsing.parseTypeDef(); declType = myJetParsing.parseTypeDef();
} }
else if (keywordToken == OBJECT_KEYWORD) { else if (keywordToken == OBJECT_KEYWORD) {
// Object expression may appear at the statement position: should parse it // Object expression may appear at the statement position: should parse it
// as expression instead of object declaration // as expression instead of object declaration
// sample: // sample:
// { // {
// object : Thread() { // object : Thread() {
// } // }
// } // }
IElementType lookahead = lookahead(1); IElementType lookahead = lookahead(1);
if (lookahead == COLON || lookahead == LBRACE) { if (lookahead == COLON || lookahead == LBRACE) {
return null; return null;
} }
myJetParsing.parseObject(true, true); myJetParsing.parseObject(true, true);
declType = OBJECT_DECLARATION; declType = OBJECT_DECLARATION;
} }
return declType; return declType;
} }
/* /*
* doWhile * doWhile
@@ -50,6 +50,7 @@ public class JetParsing extends AbstractJetParsing {
private static final TokenSet IMPORT_RECOVERY_SET = TokenSet.create(AS_KEYWORD, DOT, EOL_OR_SEMICOLON); private static final TokenSet IMPORT_RECOVERY_SET = TokenSet.create(AS_KEYWORD, DOT, EOL_OR_SEMICOLON);
/*package*/ static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, FUN_KEYWORD, LPAR, CAPITALIZED_THIS_KEYWORD, HASH); /*package*/ static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, FUN_KEYWORD, LPAR, CAPITALIZED_THIS_KEYWORD, HASH);
private static final TokenSet RECEIVER_TYPE_TERMINATORS = TokenSet.create(DOT, SAFE_ACCESS); private static final TokenSet RECEIVER_TYPE_TERMINATORS = TokenSet.create(DOT, SAFE_ACCESS);
private static final TokenSet VALUE_PARAMETER_FIRST = TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS);
static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) { static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
JetParsing jetParsing = new JetParsing(builder); JetParsing jetParsing = new JetParsing(builder);
@@ -1722,8 +1723,10 @@ public class JetParsing extends AbstractJetParsing {
else { else {
parseValueParameter(); parseValueParameter();
} }
if (!at(COMMA)) break; if (at(COMMA)) {
advance(); // COMMA advance(); // COMMA
}
else if (!atSet(VALUE_PARAMETER_FIRST)) break;
} }
} }
} }
@@ -114,7 +114,7 @@ public interface JetTokens {
JetToken SAFE_ACCESS = new JetToken("SAFE_ACCESS"); JetToken SAFE_ACCESS = new JetToken("SAFE_ACCESS");
JetToken ELVIS = new JetToken("ELVIS"); JetToken ELVIS = new JetToken("ELVIS");
// JetToken MAP = new JetToken("MAP"); // JetToken MAP = new JetToken("MAP");
// JetToken FILTER = new JetToken("FILTER"); // JetToken FILTER = new JetToken("FILTER");
JetToken QUEST = new JetToken("QUEST"); JetToken QUEST = new JetToken("QUEST");
JetToken COLONCOLON = new JetToken("COLONCOLON"); JetToken COLONCOLON = new JetToken("COLONCOLON");
JetToken COLON = new JetToken("COLON"); JetToken COLON = new JetToken("COLON");
@@ -165,23 +165,23 @@ public interface JetTokens {
JetKeywordToken FINAL_KEYWORD = JetKeywordToken.softKeyword("final"); JetKeywordToken FINAL_KEYWORD = JetKeywordToken.softKeyword("final");
TokenSet KEYWORDS = TokenSet.create(PACKAGE_KEYWORD, AS_KEYWORD, TYPE_KEYWORD, CLASS_KEYWORD, TRAIT_KEYWORD, TokenSet KEYWORDS = TokenSet.create(PACKAGE_KEYWORD, AS_KEYWORD, TYPE_KEYWORD, CLASS_KEYWORD, TRAIT_KEYWORD,
THIS_KEYWORD, SUPER_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, FOR_KEYWORD, THIS_KEYWORD, SUPER_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, FOR_KEYWORD,
NULL_KEYWORD, NULL_KEYWORD,
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD,
IN_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD, IN_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD,
ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD, TRY_KEYWORD, WHEN_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD, TRY_KEYWORD, WHEN_KEYWORD,
NOT_IN, NOT_IS, CAPITALIZED_THIS_KEYWORD, AS_SAFE NOT_IN, NOT_IS, CAPITALIZED_THIS_KEYWORD, AS_SAFE
); );
TokenSet SOFT_KEYWORDS = TokenSet.create(IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD, TokenSet SOFT_KEYWORDS = TokenSet.create(IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD,
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD,
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD
); );
TokenSet MODIFIER_KEYWORDS = TokenSet.create(ABSTRACT_KEYWORD, ENUM_KEYWORD, TokenSet MODIFIER_KEYWORDS = TokenSet.create(ABSTRACT_KEYWORD, ENUM_KEYWORD,
OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD,
PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD
); );
TokenSet WHITESPACES = TokenSet.create(TokenType.WHITE_SPACE); TokenSet WHITESPACES = TokenSet.create(TokenType.WHITE_SPACE);
@@ -196,13 +196,13 @@ public interface JetTokens {
TokenSet STRINGS = TokenSet.create(CHARACTER_LITERAL, REGULAR_STRING_PART); TokenSet STRINGS = TokenSet.create(CHARACTER_LITERAL, REGULAR_STRING_PART);
TokenSet OPERATIONS = TokenSet.create(AS_KEYWORD, AS_SAFE, IS_KEYWORD, IN_KEYWORD, DOT, PLUSPLUS, MINUSMINUS, EXCLEXCL, MUL, PLUS, TokenSet OPERATIONS = TokenSet.create(AS_KEYWORD, AS_SAFE, IS_KEYWORD, IN_KEYWORD, DOT, PLUSPLUS, MINUSMINUS, EXCLEXCL, MUL, PLUS,
MINUS, EXCL, DIV, PERC, LT, GT, LTEQ, GTEQ, EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, MINUS, EXCL, DIV, PERC, LT, GT, LTEQ, GTEQ, EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR,
SAFE_ACCESS, ELVIS, SAFE_ACCESS, ELVIS,
// MAP, FILTER, // MAP, FILTER,
COLON, COLON,
RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ, RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ,
NOT_IN, NOT_IS, NOT_IN, NOT_IS,
IDENTIFIER, LABEL_IDENTIFIER, ATAT, AT); IDENTIFIER, LABEL_IDENTIFIER, ATAT, AT);
TokenSet AUGMENTED_ASSIGNMENTS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, DIVEQ); TokenSet AUGMENTED_ASSIGNMENTS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, DIVEQ);
TokenSet ALL_ASSIGNMENTS = TokenSet.create(EQ, PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, DIVEQ); TokenSet ALL_ASSIGNMENTS = TokenSet.create(EQ, PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, DIVEQ);
@@ -0,0 +1,5 @@
val x = foo(
a,
b
c
)
@@ -0,0 +1,32 @@
JetFile: MissingCommaInValueArgumentList.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiWhiteSpace('\n ')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(COMMA)(',')
PsiWhiteSpace('\n ')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace('\n ')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('c')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n')
PsiElement(RPAR)(')')
@@ -0,0 +1,7 @@
fun foo(
a: Any,
b: Int
c: String
) {
}
@@ -0,0 +1,44 @@
JetFile: MissingCommaInValueParameterList.kt
NAMESPACE_HEADER
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiWhiteSpace('\n ')
VALUE_PARAMETER
PsiElement(IDENTIFIER)('a')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Any')
PsiElement(COMMA)(',')
PsiWhiteSpace('\n ')
VALUE_PARAMETER
PsiElement(IDENTIFIER)('b')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n ')
VALUE_PARAMETER
PsiElement(IDENTIFIER)('c')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('String')
PsiWhiteSpace('\n')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n')
PsiElement(RBRACE)('}')