match(Function);
} else {
match(Method);
}
Token name = match(Identifier);
// Parse function or method parameters
match(LeftBrace);
ArrayList<Parameter> parameters = new ArrayList<Parameter>();
HashSet<String> environment = new HashSet<String>();
boolean firstTime = true;
while (eventuallyMatch(RightBrace) == null) {
if (!firstTime) {
match(Comma);
}
firstTime = false;
int pStart = index;
Pair<SyntacticType, Token> p = parseMixedType();
Token id = p.second();
if (environment.contains(id.text)) {
syntaxError("parameter already declared", id);
}
parameters.add(wf.new Parameter(p.first(), id.text, sourceAttr(
pStart, index - 1)));
environment.add(id.text);
}
// Parse (optional) return type
TypePattern ret;
HashSet<String> ensuresEnvironment = environment;
if (tryAndMatch(true, EqualsGreater) != null) {
// Explicit return type is given, so parse it! We first clone the
// environent and create a special one only for use within ensures
// clauses, since these are the only expressions which may refer to
// variables declared in the return type.
ensuresEnvironment = new HashSet<String>(environment);
ret = parseTypePattern(ensuresEnvironment, true);
} else {
// Return type is omitted, so it is assumed to be void
SyntacticType vt = new SyntacticType.Void(sourceAttr(start,
index - 1));
ret = new TypePattern.Leaf(vt, null, sourceAttr(start, index - 1));
}
// Parse optional throws/requires/ensures clauses
ArrayList<Expr> requires = new ArrayList<Expr>();
ArrayList<Expr> ensures = new ArrayList<Expr>();
// FIXME: following should be a list!
SyntacticType throwws = new SyntacticType.Void();
Token lookahead;
while ((lookahead = tryAndMatch(true, Requires, Ensures, Throws)) != null) {
switch (lookahead.kind) {
case Requires:
// NOTE: expression terminated by ':'
requires.add(parseLogicalExpression(wf, environment, true));