* </pre>
*
* @return
*/
private Pair<SyntacticType, Token> parseMixedType() {
Token lookahead;
int start = index;
if ((lookahead = tryAndMatch(true, Function, Method)) != null) {
// At this point, we *might* have a mixed function / method type
// definition. To disambiguate, we need to see whether an identifier
// follows or not.
Token id = tryAndMatch(true, Identifier);
if (id != null) {
// Yes, we have found a mixed function / method type definition.
// Therefore, we continue to pass the remaining type parameters.
ArrayList<SyntacticType> paramTypes = new ArrayList<SyntacticType>();
match(LeftBrace);
boolean firstTime = true;
while (eventuallyMatch(RightBrace) == null) {
if (!firstTime) {
match(Comma);
}
firstTime = false;
paramTypes.add(parseUnitType());
}
SyntacticType ret;
if (lookahead.kind == Function) {
// Functions require a return type (since otherwise they are
// just nops)
match(EqualsGreater);
// Third, parse the return type
ret = parseUnitType();
} else if (tryAndMatch(true, EqualsGreater) != null) {
// Third, parse the (optional) return type. Observe that
// this is forced to be a
// unit type. This means that any tuple return types must be
// in braces. The reason for this is that a trailing comma
// may be part of an enclosing record type and we must
// disambiguate
// this.
ret = parseUnitType();
} else {
// If no return is given, then default to void.
ret = new SyntacticType.Void();
}
// Fourth, parse the optional throws type
SyntacticType throwsType = null;
if (tryAndMatch(true, Throws) != null) {
throwsType = parseType();
}
// Done
SyntacticType type;
if (lookahead.kind == Token.Kind.Function) {
type = new SyntacticType.Function(ret, throwsType,
paramTypes, sourceAttr(start, index - 1));
} else {
type = new SyntacticType.Method(ret, throwsType,
paramTypes, sourceAttr(start, index - 1));
}
return new Pair<SyntacticType, Token>(type, id);
} else {
// In this case, we failed to match a mixed type. Therefore, we
// backtrack and parse as two separate items (i.e. type
// identifier).
index = start; // backtrack
}
}
// This is the normal case, where we expect an identifier to follow the
// type.
SyntacticType type = parseType();
Token id = match(Identifier);
return new Pair<SyntacticType, Token>(type, id);
}