*
* @return
*/
private Pair<SyntacticType, Expr.Variable> parseMixedType(
HashSet<String> generics) {
Token lookahead;
int start = index;
if ((lookahead = tryAndMatch(true, Function)) != 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(generics));
}
SyntacticType ret;
// Functions require a return type (since otherwise they are
// just nops)
match(EqualsGreater);
// Third, parse the return type
ret = parseUnitType(generics);
// Fourth, parse the optional throws type
SyntacticType throwsType = null;
if (tryAndMatch(true, Throws) != null) {
throwsType = parseType(generics);
}
// Done
SyntacticType type = new SyntacticType.Function(ret,
throwsType, paramTypes, sourceAttr(start, index - 1));
return new Pair<SyntacticType, Expr.Variable>(type,
new Expr.Variable(id.text, sourceAttr(id.start,
id.end())));
} 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(generics);
Token id = match(Identifier);
return new Pair<SyntacticType, Expr.Variable>(type, new Expr.Variable(
id.text, sourceAttr(id.start, id.end())));
}