Index: uspace/app/sbi/src/p_expr.c
===================================================================
--- uspace/app/sbi/src/p_expr.c	(revision 37f527bc07305262cbe6d63e6c152419e5050304)
+++ uspace/app/sbi/src/p_expr.c	(revision 9f10660f34e7fc98fc93338eaf64f0d8bd82da7a)
@@ -31,4 +31,5 @@
 #include <assert.h>
 #include <stdlib.h>
+#include "debug.h"
 #include "lex.h"
 #include "list.h"
@@ -57,11 +58,31 @@
 static stree_expr_t *parse_self_ref(parse_t *parse);
 
-/** Parse expression. */
+static stree_expr_t *parse_recovery_expr(parse_t *parse);
+
+/** Parse expression.
+ *
+ * Input is read from the input object associated with @a parse. If any
+ * error occurs, parse->error will @c b_true when this function
+ * returns. parse->error_bailout will be @c b_true if the error has not
+ * been recovered yet. Similar holds for other parsing functions in this
+ * module.
+ *
+ * @param parse		Parser object.
+ */
 stree_expr_t *parse_expr(parse_t *parse)
 {
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parse expression.\n");
+#endif
+	if (parse_is_error(parse))
+		return parse_recovery_expr(parse);
+
 	return parse_assign(parse);
 }
 
-/** Parse assignment expression. */
+/** Parse assignment expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_assign(parse_t *parse)
 {
@@ -93,5 +114,8 @@
 }
 
-/** Parse comparative expression. */
+/** Parse comparative expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_comparative(parse_t *parse)
 {
@@ -105,4 +129,7 @@
 	    lcur_lc(parse) == lc_lt || lcur_lc(parse) == lc_gt ||
 	    lcur_lc(parse) == lc_lt_equal || lcur_lc(parse) == lc_gt_equal) {
+
+		if (parse_is_error(parse))
+			break;
 
 		switch (lcur_lc(parse)) {
@@ -131,5 +158,8 @@
 }
 
-/** Parse additive expression. */
+/** Parse additive expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_additive(parse_t *parse)
 {
@@ -139,4 +169,7 @@
 	a = parse_prefix(parse);
 	while (lcur_lc(parse) == lc_plus) {
+		if (parse_is_error(parse))
+			break;
+
 		lskip(parse);
 		b = parse_prefix(parse);
@@ -154,5 +187,8 @@
 }
 
-/** Parse prefix expression. */
+/** Parse prefix expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_prefix(parse_t *parse)
 {
@@ -162,5 +198,7 @@
 	case lc_plus:
 		printf("Unimplemented: Unary plus.\n");
-		exit(1);
+		a = parse_recovery_expr(parse);
+		parse_note_error(parse);
+		break;
 	case lc_new:
 		a = parse_prefix_new(parse);
@@ -174,5 +212,8 @@
 }
 
-/** Parse @c new operator. */
+/** Parse @c new operator.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_prefix_new(parse_t *parse)
 {
@@ -198,5 +239,8 @@
 }
 
-/** Parse postfix expression. */
+/** Parse postfix expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_postfix(parse_t *parse)
 {
@@ -208,4 +252,7 @@
 	while (lcur_lc(parse) == lc_period || lcur_lc(parse) == lc_lparen ||
 	    lcur_lc(parse) == lc_lsbr || lcur_lc(parse) == lc_as) {
+
+		if (parse_is_error(parse))
+			break;
 
 		switch (lcur_lc(parse)) {
@@ -232,5 +279,8 @@
 }
 
-/** Parse member access expression */
+/** Parse member access expression
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a)
 {
@@ -252,5 +302,8 @@
 }
 
-/** Parse function call expression. */
+/** Parse function call expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a)
 {
@@ -268,5 +321,5 @@
 
 	if (lcur_lc(parse) != lc_rparen) {
-		while (b_true) {
+		while (!parse_is_error(parse)) {
 			arg = parse_expr(parse);
 			list_append(&call->args, arg);
@@ -286,5 +339,8 @@
 }
 
-/** Parse index expression. */
+/** Parse index expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a)
 {
@@ -302,5 +358,5 @@
 
 	if (lcur_lc(parse) != lc_rsbr) {
-		while (b_true) {
+		while (!parse_is_error(parse)) {
 			arg = parse_expr(parse);
 			list_append(&index->args, arg);
@@ -320,5 +376,8 @@
 }
 
-/** Parse @c as operator. */
+/** Parse @c as operator.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a)
 {
@@ -339,5 +398,8 @@
 }
 
-/** Parse primitive expression. */
+/** Parse primitive expression.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_primitive(parse_t *parse)
 {
@@ -362,11 +424,14 @@
 	default:
 		lunexpected_error(parse);
-		exit(1);
-	}
-
-	return expr;
-}
-
-/** Parse name reference. */
+		expr = parse_recovery_expr(parse);
+	}
+
+	return expr;
+}
+
+/** Parse name reference.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_nameref(parse_t *parse)
 {
@@ -382,5 +447,8 @@
 }
 
-/** Parse integer literal. */
+/** Parse integer literal.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_lit_int(parse_t *parse)
 {
@@ -401,5 +469,8 @@
 }
 
-/** Parse reference literal (@c nil). */
+/** Parse reference literal (@c nil).
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_lit_ref(parse_t *parse)
 {
@@ -417,5 +488,8 @@
 }
 
-/** Parse string literal. */
+/** Parse string literal.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_lit_string(parse_t *parse)
 {
@@ -436,5 +510,8 @@
 }
 
-/** Parse @c self keyword. */
+/** Parse @c self keyword.
+ *
+ * @param parse		Parser object.
+ */
 static stree_expr_t *parse_self_ref(parse_t *parse)
 {
@@ -451,2 +528,21 @@
 	return expr;
 }
+
+/** Construct a special recovery expression.
+ *
+ * @param parse		Parser object.
+ */
+static stree_expr_t *parse_recovery_expr(parse_t *parse)
+{
+	stree_literal_t *literal;
+	stree_expr_t *expr;
+
+	(void) parse;
+
+	literal = stree_literal_new(ltc_ref);
+
+	expr = stree_expr_new(ec_literal);
+	expr->u.literal = literal;
+
+	return expr;
+}
