Index: uspace/app/bithenge/expression.c
===================================================================
--- uspace/app/bithenge/expression.c	(revision 10334c2e815ecb663ac16f1964110930706dc263)
+++ uspace/app/bithenge/expression.c	(revision 20ac1a4d9f8ba1e4a74ec7c3fe780a46f6c47167)
@@ -420,4 +420,86 @@
 	bithenge_transform_t base;
 	bithenge_expression_t *expr;
+} expression_transform_t;
+
+static inline bithenge_transform_t *expression_as_transform(
+    expression_transform_t *self)
+{
+	return &self->base;
+}
+
+static inline expression_transform_t *transform_as_expression(
+    bithenge_transform_t *base)
+{
+	return (expression_transform_t *)base;
+}
+
+static int expression_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	expression_transform_t *self = transform_as_expression(base);
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	aoff64_t len;
+	int rc = bithenge_blob_size(bithenge_node_as_blob(in), &len);
+	if (rc != EOK)
+		return rc;
+	if (len != 0)
+		return EINVAL;
+	return bithenge_expression_evaluate(self->expr, scope, out);
+}
+
+static int expression_transform_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
+{
+	*out = 0;
+	return EOK;
+}
+
+static void expression_transform_destroy(bithenge_transform_t *base)
+{
+	expression_transform_t *self = transform_as_expression(base);
+	bithenge_expression_dec_ref(self->expr);
+	free(self);
+}
+
+static const bithenge_transform_ops_t expression_transform_ops = {
+	.apply = expression_transform_apply,
+	.prefix_length = expression_transform_prefix_length,
+	.destroy = expression_transform_destroy,
+};
+
+/** Create a transform that takes an empty blob and produces the result of an
+ * expression. Takes a reference to the expression.
+ * @param[out] out Holds the new transform.
+ * @param expr The expression to evaluate.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_expression_transform(bithenge_transform_t ** out,
+    bithenge_expression_t *expr)
+{
+	int rc;
+	expression_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(expression_as_transform(self),
+	    &expression_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	*out = expression_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	return rc;
+}
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_expression_t *expr;
 	bithenge_transform_t *true_xform, *false_xform;
 } if_transform_t;
Index: uspace/app/bithenge/expression.h
===================================================================
--- uspace/app/bithenge/expression.h	(revision 10334c2e815ecb663ac16f1964110930706dc263)
+++ uspace/app/bithenge/expression.h	(revision 20ac1a4d9f8ba1e4a74ec7c3fe780a46f6c47167)
@@ -100,4 +100,6 @@
 int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *,
     bithenge_expression_t **);
+int bithenge_expression_transform(bithenge_transform_t **,
+    bithenge_expression_t *);
 int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *,
     bithenge_transform_t *, bithenge_transform_t *);
Index: uspace/app/bithenge/script.c
===================================================================
--- uspace/app/bithenge/script.c	(revision 10334c2e815ecb663ac16f1964110930706dc263)
+++ uspace/app/bithenge/script.c	(revision 20ac1a4d9f8ba1e4a74ec7c3fe780a46f6c47167)
@@ -342,4 +342,5 @@
 
 static bithenge_transform_t *parse_transform(state_t *state);
+static bithenge_transform_t *parse_struct(state_t *state);
 
 static bithenge_expression_t *parse_expression(state_t *state)
@@ -490,5 +491,5 @@
 }
 
-static bithenge_transform_t *parse_if(state_t *state)
+static bithenge_transform_t *parse_if(state_t *state, bool in_struct)
 {
 	expect(state, TOKEN_IF);
@@ -497,11 +498,39 @@
 	expect(state, ')');
 	expect(state, '{');
-	bithenge_transform_t *true_xform = parse_transform(state);
+	bithenge_transform_t *true_xform =
+	    in_struct ? parse_struct(state) : parse_transform(state);
 	expect(state, '}');
-	expect(state, TOKEN_ELSE);
-	expect(state, '{');
-	bithenge_transform_t *false_xform = parse_transform(state);
-	expect(state, '}');
+	bithenge_transform_t *false_xform = NULL;
+	if (state->token == TOKEN_ELSE) {
+		next_token(state);
+		expect(state, '{');
+		false_xform =
+		    in_struct ? parse_struct(state) : parse_transform(state);
+		expect(state, '}');
+	} else {
+		if (in_struct) {
+			bithenge_node_t *node;
+			int rc = bithenge_new_empty_internal_node(&node);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				goto error;
+			}
+			bithenge_expression_t *expr;
+			rc = bithenge_const_expression(&expr, node);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				goto error;
+			}
+			rc = bithenge_expression_transform(&false_xform, expr);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				false_xform = NULL;
+				goto error;
+			}
+		} else
+			syntax_error(state, "else expected");
+	}
 	if (state->error != EOK) {
+error:
 		bithenge_expression_dec_ref(expr);
 		bithenge_transform_dec_ref(true_xform);
@@ -519,4 +548,5 @@
 }
 
+/* The TOKEN_STRUCT and '{' must already have been skipped. */
 static bithenge_transform_t *parse_struct(state_t *state)
 {
@@ -525,22 +555,23 @@
 	/* We keep an extra space for the {NULL, NULL} terminator. */
 	subxforms = state_malloc(state, sizeof(*subxforms));
-	expect(state, TOKEN_STRUCT);
-	expect(state, '{');
 	while (state->error == EOK && state->token != '}') {
-		if (state->token == '.') {
-			expect(state, '.');
-			subxforms[num].name = expect_identifier(state);
+		if (state->token == TOKEN_IF) {
+			subxforms[num].transform = parse_if(state, true);
+			subxforms[num].name = NULL;
+		} else {
+			if (state->token == '.') {
+				next_token(state);
+				subxforms[num].name = expect_identifier(state);
+			} else {
+				subxforms[num].name = NULL;
+			}
 			expect(state, TOKEN_LEFT_ARROW);
-		} else {
-			subxforms[num].name = NULL;
-			expect(state, TOKEN_LEFT_ARROW);
-		}
-		subxforms[num].transform = parse_transform(state);
-		expect(state, ';');
+			subxforms[num].transform = parse_transform(state);
+			expect(state, ';');
+		}
 		num++;
 		subxforms = state_realloc(state, subxforms,
 		    (num + 1)*sizeof(*subxforms));
 	}
-	expect(state, '}');
 
 	if (state->error != EOK) {
@@ -571,7 +602,11 @@
 		return parse_invocation(state);
 	} else if (state->token == TOKEN_IF) {
-		return parse_if(state);
+		return parse_if(state, false);
 	} else if (state->token == TOKEN_STRUCT) {
-		return parse_struct(state);
+		next_token(state);
+		expect(state, '{');
+		bithenge_transform_t *xform = parse_struct(state);
+		expect(state, '}');
+		return xform;
 	} else {
 		syntax_error(state, "unexpected (transform expected)");
