Index: uspace/app/bithenge/script.c
===================================================================
--- uspace/app/bithenge/script.c	(revision 0153c87e5c9c1080a884969b29e7aa3388bd5a64)
+++ uspace/app/bithenge/script.c	(revision 2988aec7d345a3d82047f938825fde9cb05c261c)
@@ -53,6 +53,9 @@
  * other token uses one of these values: */
 typedef enum {
-	TOKEN_EQUALS = -128,
-	TOKEN_ERROR,
+	TOKEN_ERROR = -128,
+
+	TOKEN_AND,
+	TOKEN_CONCAT,
+	TOKEN_EQUALS,
 	TOKEN_EOF,
 	TOKEN_GREATER_THAN_OR_EQUAL,
@@ -63,4 +66,5 @@
 	TOKEN_LESS_THAN_OR_EQUAL,
 	TOKEN_NOT_EQUAL,
+	TOKEN_OR,
 
 	/* Keywords */
@@ -308,4 +312,25 @@
 			state->buffer_pos++;
 		}
+	} else if (ch == '&') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '&') {
+			state->token = TOKEN_AND;
+			state->buffer_pos++;
+		}
+	} else if (ch == '|') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '|') {
+			state->token = TOKEN_OR;
+			state->buffer_pos++;
+		}
+	} else if (ch == '+') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '+') {
+			state->token = TOKEN_CONCAT;
+			state->buffer_pos++;
+		}
 	} else {
 		state->token = ch;
@@ -415,4 +440,5 @@
 typedef enum {
 	PRECEDENCE_NONE,
+	PRECEDENCE_AND,
 	PRECEDENCE_EQUALS,
 	PRECEDENCE_COMPARE,
@@ -446,4 +472,10 @@
 	case TOKEN_NOT_EQUAL:
 		return BITHENGE_EXPRESSION_NOT_EQUALS;
+	case TOKEN_AND:
+		return BITHENGE_EXPRESSION_AND;
+	case TOKEN_OR:
+		return BITHENGE_EXPRESSION_OR;
+	case TOKEN_CONCAT:
+		return BITHENGE_EXPRESSION_CONCAT;
 	default:
 		return BITHENGE_EXPRESSION_INVALID_BINARY_OP;
@@ -455,5 +487,6 @@
 	switch (op) {
 	case BITHENGE_EXPRESSION_ADD: /* fallthrough */
-	case BITHENGE_EXPRESSION_SUBTRACT:
+	case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
+	case BITHENGE_EXPRESSION_CONCAT:
 		return PRECEDENCE_ADD;
 	case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
@@ -469,4 +502,7 @@
 	case BITHENGE_EXPRESSION_NOT_EQUALS:
 		return PRECEDENCE_EQUALS;
+	case BITHENGE_EXPRESSION_AND: /* fallthrough */
+	case BITHENGE_EXPRESSION_OR:
+		return PRECEDENCE_AND;
 	default:
 		assert(false);
@@ -609,5 +645,14 @@
 			}
 
-			rc = bithenge_member_expression(&expr, expr, key);
+			bithenge_expression_t *key_expr;
+			rc = bithenge_const_expression(&key_expr, key);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				bithenge_expression_dec_ref(expr);
+				return NULL;
+			}
+
+			rc = bithenge_binary_expression(&expr,
+			    BITHENGE_EXPRESSION_MEMBER, expr, key_expr);
 			if (rc != EOK) {
 				error_errno(state, rc);
@@ -618,28 +663,42 @@
 			bithenge_expression_t *start = parse_expression(state);
 			bool absolute_limit = false;
-			if (state->token == ',') {
-				absolute_limit = false;
+			if (state->token == ',' || state->token == ':') {
+				absolute_limit = state->token == ':';
 				next_token(state);
-			} else if (state->token == ':') {
-				absolute_limit = true;
+				bithenge_expression_t *limit = NULL;
+				if (!(state->token == ']' && absolute_limit))
+					limit = parse_expression(state);
+				expect(state, ']');
+
+				if (state->error != EOK) {
+					bithenge_expression_dec_ref(expr);
+					bithenge_expression_dec_ref(start);
+					bithenge_expression_dec_ref(limit);
+					return NULL;
+				}
+				rc = bithenge_subblob_expression(&expr, expr, start,
+				    limit, absolute_limit);
+				if (rc != EOK) {
+					error_errno(state, rc);
+					return NULL;
+				}
+			} else if (state->token == ']') {
 				next_token(state);
+
+				if (state->error != EOK) {
+					bithenge_expression_dec_ref(expr);
+					bithenge_expression_dec_ref(start);
+					return NULL;
+				}
+				rc = bithenge_binary_expression(&expr,
+				    BITHENGE_EXPRESSION_MEMBER, expr, start);
+				if (rc != EOK) {
+					error_errno(state, rc);
+					return NULL;
+				}
 			} else {
-				syntax_error(state, "expected ',' or ':'");
-			}
-			bithenge_expression_t *limit = NULL;
-			if (!(state->token == ']' && absolute_limit))
-				limit = parse_expression(state);
-			expect(state, ']');
-
-			if (state->error != EOK) {
+				syntax_error(state, "expected ',', ':', or ']'");
 				bithenge_expression_dec_ref(expr);
 				bithenge_expression_dec_ref(start);
-				bithenge_expression_dec_ref(limit);
-				return NULL;
-			}
-			rc = bithenge_subblob_expression(&expr, expr, start,
-			    limit, absolute_limit);
-			if (rc != EOK) {
-				error_errno(state, rc);
 				return NULL;
 			}
@@ -1173,4 +1232,16 @@
 	}
 
+	bithenge_transform_t *barrier = NULL;
+	if (state->error == EOK) {
+		int rc = bithenge_new_barrier_transform(&barrier,
+		    state->num_params);
+		if (rc != EOK) {
+			barrier = NULL;
+			error_errno(state, rc);
+		}
+	}
+
+	add_named_transform(state, barrier, name);
+
 	expect(state, '=');
 	bithenge_transform_t *xform = parse_transform(state);
@@ -1178,13 +1249,13 @@
 
 	if (state->error == EOK) {
-		int rc = bithenge_new_barrier_transform(&xform, xform,
-		    state->num_params);
-		if (rc != EOK) {
-			xform = NULL;
-			error_errno(state, rc);
-		}
-	}
-
-	add_named_transform(state, xform, name);
+		int rc = bithenge_barrier_transform_set_subtransform(barrier,
+		    xform);
+		xform = NULL;
+		if (rc != EOK)
+			error_errno(state, rc);
+	}
+
+	if (state->error != EOK)
+		bithenge_transform_dec_ref(xform);
 
 	for (int i = 0; i < state->num_params; i++)
