Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 074444f189ee9356421b26e70454fae61c81def3)
+++ uspace/app/sbi/src/parse.c	(revision 38aaacc20a85af2361a0240ac2e7d643e086ecfa)
@@ -54,4 +54,5 @@
 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
 
+static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi);
 static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi);
 static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi);
@@ -62,4 +63,6 @@
 static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
 static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
+static stree_fun_sig_t *parse_fun_sig(parse_t *parse);
+
 
 /*
@@ -157,4 +160,5 @@
 	stree_symbol_t *symbol;
 	stree_ident_t *targ_name;
+	stree_targ_t *targ;
 
 	switch (dclass) {
@@ -170,10 +174,14 @@
 	csi->name = parse_ident(parse);
 
-	list_init(&csi->targ_names);
+	list_init(&csi->targ);
 
 	while (lcur_lc(parse) == lc_slash) {
 		lskip(parse);
 		targ_name = parse_ident(parse);
-		list_append(&csi->targ_names, targ_name);
+
+		targ = stree_targ_new();
+		targ->name = targ_name;
+
+		list_append(&csi->targ, targ);
 	}
 
@@ -201,4 +209,7 @@
 	while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
 		csimbr = parse_csimbr(parse, csi);
+		if (csimbr == NULL)
+			break;
+
 		list_append(&csi->members, csimbr);
 	}
@@ -213,5 +224,6 @@
  * @param parse		Parser object.
  * @param outer_csi	CSI containing this declaration or @c NULL if global.
- * @return		New syntax tree node.
+ * @return		New syntax tree node. In case of parse error,
+ *			@c NULL may (but need not) be returned.
  */
 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
@@ -220,4 +232,5 @@
 
 	stree_csi_t *csi;
+	stree_deleg_t *deleg;
 	stree_fun_t *fun;
 	stree_var_t *var;
@@ -232,4 +245,9 @@
 		csimbr->u.csi = csi;
 		break;
+	case lc_deleg:
+		deleg = parse_deleg(parse, outer_csi);
+		csimbr = stree_csimbr_new(csimbr_deleg);
+		csimbr->u.deleg = deleg;
+		break;
 	case lc_fun:
 		fun = parse_fun(parse, outer_csi);
@@ -250,4 +268,6 @@
 		lunexpected_error(parse);
 		lex_next(parse->lex);
+		csimbr = NULL;
+		break;
 	}
 
@@ -255,4 +275,45 @@
 }
 
+/** Parse delegate.
+ *
+ * @param parse		Parser object.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
+static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi)
+{
+	stree_deleg_t *deleg;
+	stree_symbol_t *symbol;
+	stree_symbol_attr_t *attr;
+
+	deleg = stree_deleg_new();
+	symbol = stree_symbol_new(sc_deleg);
+
+	symbol->u.deleg = deleg;
+	symbol->outer_csi = outer_csi;
+	deleg->symbol = symbol;
+
+	lmatch(parse, lc_deleg);
+	deleg->name = parse_ident(parse);
+
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parsing delegate '%s'.\n", strtab_get_str(deleg->name->sid));
+#endif
+
+	deleg->sig = parse_fun_sig(parse);
+
+	list_init(&symbol->attr);
+
+	/* Parse attributes. */
+	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
+		lskip(parse);
+		attr = parse_symbol_attr(parse);
+		list_append(&symbol->attr, attr);
+	}
+
+	lmatch(parse, lc_scolon);
+
+	return deleg;
+}
 
 /** Parse member function.
@@ -265,5 +326,4 @@
 {
 	stree_fun_t *fun;
-	stree_proc_arg_t *arg;
 	stree_symbol_t *symbol;
 	stree_symbol_attr_t *attr;
@@ -278,40 +338,9 @@
 	lmatch(parse, lc_fun);
 	fun->name = parse_ident(parse);
-	lmatch(parse, lc_lparen);
 
 #ifdef DEBUG_PARSE_TRACE
 	printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
 #endif
-
-	list_init(&fun->args);
-
-	if (lcur_lc(parse) != lc_rparen) {
-
-		/* Parse formal parameters. */
-		while (!parse_is_error(parse)) {
-			arg = parse_proc_arg(parse);
-
-			if (stree_arg_has_attr(arg, aac_packed)) {
-				fun->varg = arg;
-				break;
-			} else {
-				list_append(&fun->args, arg);
-			}
-
-			if (lcur_lc(parse) == lc_rparen)
-				break;
-
-			lmatch(parse, lc_scolon);
-		}
-	}
-
-	lmatch(parse, lc_rparen);
-
-	if (lcur_lc(parse) == lc_colon) {
-	    	lskip(parse);
-		fun->rtype = parse_texpr(parse);
-	} else {
-		fun->rtype = NULL;
-	}
+	fun->sig = parse_fun_sig(parse);
 
 	list_init(&symbol->attr);
@@ -522,5 +551,8 @@
 	arg->type = parse_texpr(parse);
 
-	list_init(&arg->attr);
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parse procedure argument.\n");
+#endif
+ 	list_init(&arg->attr);
 
 	/* Parse attributes. */
@@ -531,7 +563,4 @@
 	}
 
-#ifdef DEBUG_PARSE_TRACE
-	printf("Parsed arg attr, type=%p.\n", arg->type);
-#endif
 	return arg;
 }
@@ -557,4 +586,56 @@
 	attr = stree_arg_attr_new(aac_packed);
 	return attr;
+}
+
+/** Parse function signature.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
+static stree_fun_sig_t *parse_fun_sig(parse_t *parse)
+{
+	stree_fun_sig_t *sig;
+	stree_proc_arg_t *arg;
+
+	sig = stree_fun_sig_new();
+
+	lmatch(parse, lc_lparen);
+
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parsing function signature.\n");
+#endif
+
+	list_init(&sig->args);
+
+	if (lcur_lc(parse) != lc_rparen) {
+
+		/* Parse formal parameters. */
+		while (!parse_is_error(parse)) {
+			arg = parse_proc_arg(parse);
+
+			if (stree_arg_has_attr(arg, aac_packed)) {
+				sig->varg = arg;
+				break;
+			} else {
+				list_append(&sig->args, arg);
+			}
+
+			if (lcur_lc(parse) == lc_rparen)
+				break;
+
+			lmatch(parse, lc_scolon);
+		}
+	}
+
+	lmatch(parse, lc_rparen);
+
+	if (lcur_lc(parse) == lc_colon) {
+	    	lskip(parse);
+		sig->rtype = parse_texpr(parse);
+	} else {
+		sig->rtype = NULL;
+	}
+
+	return sig;
 }
 
