Index: uspace/app/bithenge/expression.c
===================================================================
--- uspace/app/bithenge/expression.c	(revision c12b2ae082eac0a7d4f9b390d096717c290f3211)
+++ uspace/app/bithenge/expression.c	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
@@ -94,9 +94,42 @@
 		return rc;
 	}
+
+	/* Check types and get values. */
+	bithenge_int_t a_int, b_int;
 	switch (self->op) {
+	case BITHENGE_EXPRESSION_ADD: /* fallthrough */
+	case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
+	case BITHENGE_EXPRESSION_MULTIPLY:
+		rc = EINVAL;
+		if (bithenge_node_type(a) != BITHENGE_NODE_INTEGER)
+			goto error;
+		if (bithenge_node_type(b) != BITHENGE_NODE_INTEGER)
+			goto error;
+		a_int = bithenge_integer_node_value(a);
+		b_int = bithenge_integer_node_value(b);
+		break;
+	default:
+		break;
+	}
+
+	switch (self->op) {
+	case BITHENGE_EXPRESSION_ADD:
+		rc = bithenge_new_integer_node(out, a_int + b_int);
+		break;
+	case BITHENGE_EXPRESSION_SUBTRACT:
+		rc = bithenge_new_integer_node(out, a_int - b_int);
+		break;
+	case BITHENGE_EXPRESSION_MULTIPLY:
+		rc = bithenge_new_integer_node(out, a_int * b_int);
+		break;
 	case BITHENGE_EXPRESSION_EQUALS:
 		rc = bithenge_new_boolean_node(out, bithenge_node_equal(a, b));
 		break;
-	}
+	case BITHENGE_EXPRESSION_INVALID_BINARY_OP:
+		assert(false);
+		break;
+	}
+
+error:
 	bithenge_node_dec_ref(a);
 	bithenge_node_dec_ref(b);
Index: uspace/app/bithenge/expression.h
===================================================================
--- uspace/app/bithenge/expression.h	(revision c12b2ae082eac0a7d4f9b390d096717c290f3211)
+++ uspace/app/bithenge/expression.h	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
@@ -92,4 +92,8 @@
 
 typedef enum {
+	BITHENGE_EXPRESSION_INVALID_BINARY_OP,
+	BITHENGE_EXPRESSION_ADD,
+	BITHENGE_EXPRESSION_SUBTRACT,
+	BITHENGE_EXPRESSION_MULTIPLY,
 	BITHENGE_EXPRESSION_EQUALS,
 } bithenge_binary_op_t;
Index: uspace/app/bithenge/script.c
===================================================================
--- uspace/app/bithenge/script.c	(revision c12b2ae082eac0a7d4f9b390d096717c290f3211)
+++ uspace/app/bithenge/script.c	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
@@ -52,5 +52,6 @@
  * other token uses one of these values: */
 typedef enum {
-	TOKEN_ERROR = -128,
+	TOKEN_EQUALS = -128,
+	TOKEN_ERROR,
 	TOKEN_EOF,
 	TOKEN_IDENTIFIER,
@@ -261,4 +262,11 @@
 			state->token = TOKEN_LEFT_ARROW;
 		}
+	} else if (ch == '=') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '=') {
+			state->token = TOKEN_EQUALS;
+			state->buffer_pos++;
+		}
 	} else {
 		state->token = ch;
@@ -360,6 +368,50 @@
 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)
+static bithenge_expression_t *parse_expression(state_t *state);
+
+
+
+/***************** Expressions                               *****************/
+
+typedef enum {
+	PRECEDENCE_NONE,
+	PRECEDENCE_EQUALS,
+	PRECEDENCE_ADD,
+	PRECEDENCE_MULTIPLY,
+} precedence_t;
+
+static bithenge_binary_op_t token_as_binary_operator(token_type_t token)
+{
+	switch ((int)token) {
+	case '+':
+		return BITHENGE_EXPRESSION_ADD;
+	case '-':
+		return BITHENGE_EXPRESSION_SUBTRACT;
+	case '*':
+		return BITHENGE_EXPRESSION_MULTIPLY;
+	case TOKEN_EQUALS:
+		return BITHENGE_EXPRESSION_EQUALS;
+	default:
+		return BITHENGE_EXPRESSION_INVALID_BINARY_OP;
+	}
+}
+
+static precedence_t binary_operator_precedence(bithenge_binary_op_t op)
+{
+	switch (op) {
+	case BITHENGE_EXPRESSION_ADD: /* fallthrough */
+	case BITHENGE_EXPRESSION_SUBTRACT:
+		return PRECEDENCE_ADD;
+	case BITHENGE_EXPRESSION_MULTIPLY:
+		return PRECEDENCE_MULTIPLY;
+	case BITHENGE_EXPRESSION_EQUALS:
+		return PRECEDENCE_EQUALS;
+	default:
+		assert(false);
+		return PRECEDENCE_NONE;
+	}
+}
+
+static bithenge_expression_t *parse_term(state_t *state)
 {
 	int rc;
@@ -451,4 +503,9 @@
 
 		return expr;
+	} else if (state->token == '(') {
+		next_token(state);
+		bithenge_expression_t *expr = parse_expression(state);
+		expect(state, ')');
+		return expr;
 	} else {
 		syntax_error(state, "expression expected");
@@ -457,5 +514,42 @@
 }
 
-// state->token must be TOKEN_IDENTIFIER when this is called
+static bithenge_expression_t *parse_expression_precedence(state_t *state,
+    precedence_t prev_precedence)
+{
+	bithenge_expression_t *expr = parse_term(state);
+	while (state->error == EOK) {
+		bithenge_binary_op_t op =
+		    token_as_binary_operator(state->token);
+		if (op == BITHENGE_EXPRESSION_INVALID_BINARY_OP)
+			break;
+		precedence_t precedence = binary_operator_precedence(op);
+		if (precedence <= prev_precedence)
+			break;
+		next_token(state);
+
+		bithenge_expression_t *expr2 = parse_term(state);
+		if (state->error != EOK) {
+			bithenge_expression_dec_ref(expr2);
+			break;
+		}
+		int rc = bithenge_binary_expression(&expr, op, expr, expr2);
+		if (rc != EOK)
+			error_errno(state, rc);
+	}
+	if (state->error != EOK) {
+		bithenge_expression_dec_ref(expr);
+		expr = NULL;
+	}
+	return expr;
+}
+
+static bithenge_expression_t *parse_expression(state_t *state)
+{
+	return parse_expression_precedence(state, PRECEDENCE_NONE);
+}
+
+
+
+/* state->token must be TOKEN_IDENTIFIER when this is called. */
 static bithenge_transform_t *parse_invocation(state_t *state)
 {
