code: private AstFunction parseFunctionDefinition() {
      eatChar('{');
  
      // Parse the list of ids
      ArrayList<String> ids = new ArrayList<>();
      ids.add("");  // 1-based ID list
      while (skipWS() != '.') {
        String id = token();
        if (!Character.isJavaIdentifierStart(id.charAt(0)))
          throw new IllegalASTException("variable must be a valid Java identifier: " + id);
        for (char c : id.toCharArray())
          if (!Character.isJavaIdentifierPart(c))
            throw new IllegalASTException("variable must be a valid Java identifier: " + id);
        ids.add(id);
      }
  
      // Single dot separates the list of ids from the body of the function
      eatChar('.');
  
      // Parse the body
      AstRoot body = parseNext();
      if (skipWS() != '}')
        throw new IllegalASTException("Expected the end of the function, but found '" + peek(0) + "'");
      eatChar('}');
  
      return new AstFunction(ids, body);
    }
docs: Parse and return a user defined function of the form "{arg1 arg2 . (expr)}"