Index: uspace/app/sbi/Makefile
===================================================================
--- uspace/app/sbi/Makefile	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/Makefile	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2010 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBC_PREFIX)/libc.a
+EXTRA_CFLAGS = -D__HELENOS__
+
+OUTPUT = sbi
+
+SOURCES = \
+	src/ancr.c \
+	src/builtin.c \
+	src/input.c \
+	src/intmap.c \
+	src/lex.c \
+	src/list.c \
+	src/main.c \
+	src/p_expr.c \
+	src/p_type.c \
+	src/parse.c \
+	src/rdata.c \
+	src/run.c \
+	src/run_expr.c \
+	src/stree.c \
+	src/strtab.c \
+	src/symbol.c
+
+include ../Makefile.common
Index: uspace/app/sbi/src/ancr.c
===================================================================
--- uspace/app/sbi/src/ancr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/ancr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Ancestry resolver.
+ *
+ * A chicken-and-egg problem is that in order to match identifiers to CSI
+ * definitions we need to know CSI ancestry. To know CSI ancestry we need
+ * to match identifiers to CSI definitions. Thus both must be done at the
+ * same time. Once we know the ancestry of some CSI, we are able to resolve
+ * symbols referenced within the scope of that CSI (but not in nested scopes).
+ *
+ * Here lies probably the most complicated (although not so complicated)
+ * algorithm. To process node N we must first process outer(N). This allows
+ * us to find all base(N) nodes and process them.
+ *
+ * To ensure all nodes get processed correctly, we use a two-layer walk.
+ * In the lower layer (ancr_csi_process) we follow the dependencies.
+ * ancr_csi_process(N) ensures N (and possibly other nodes) get resolved.
+ *
+ * In the second layer we simply do a DFS of the CSI tree, calling
+ * ancr_csi_process() on each node. This ensures that eventually all
+ * nodes get processed.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include "list.h"
+#include "mytypes.h"
+#include "stree.h"
+#include "strtab.h"
+#include "symbol.h"
+
+#include "ancr.h"
+
+static void ancr_csi_dfs(stree_program_t *prog, stree_csi_t *csi);
+static void ancr_csi_process(stree_program_t *prog, stree_csi_t *node);
+static void ancr_csi_print_cycle(stree_program_t *prog, stree_csi_t *node);
+
+/** Process ancestry of all CSIs in a module.
+ *
+ * Note that currently we expect there to be exactly one module in the
+ * whole program.
+ */
+void ancr_module_process(stree_program_t *prog, stree_module_t *module)
+{
+	list_node_t *node;
+	stree_modm_t *modm;
+
+	node = list_first(&prog->module->members);
+
+	while (node != NULL) {
+		modm = list_node_data(node, stree_modm_t *);
+		assert(modm->mc == mc_csi); /* XXX */
+/*		printf("ancr_csi_process() on '%s'\n",
+		    strtab_get_str(modm->u.csi->name->sid));*/
+		ancr_csi_dfs(prog, modm->u.csi);
+
+		node = list_next(&prog->module->members, node);
+	}
+}
+
+/** Walk CSI node tree depth-first.
+ *
+ * This is the outer depth-first walk whose purpose is to eventually
+ * process all CSI nodes by calling ancr_csi_process() on them.
+ * (Which causes that and possibly some other nodes to be processed).
+ */
+static void ancr_csi_dfs(stree_program_t *prog, stree_csi_t *csi)
+{
+	list_node_t *node;
+	stree_csimbr_t *csimbr;
+
+	/* Process this node first. */
+	ancr_csi_process(prog, csi);
+
+	/* Now visit all children. */
+	node = list_first(&csi->members);
+	while (node != NULL) {
+		csimbr = list_node_data(node, stree_csimbr_t *);
+		if (csimbr->cc == csimbr_csi)
+			ancr_csi_dfs(prog, csimbr->u.csi);
+
+		node = list_next(&csi->members, node);
+	}
+}
+
+/** Process csi node.
+ *
+ * Fist processes the pre-required nodes (outer CSI and base CSIs),
+ * then processes @a node. This is the core 'outward-and-baseward' walk.
+ */
+static void ancr_csi_process(stree_program_t *prog, stree_csi_t *node)
+{
+	stree_symbol_t *base_sym;
+	stree_csi_t *base_csi, *outer_csi;
+
+	if (node->ancr_state == ws_visited) {
+		/* Node already processed */
+		return;
+	}
+
+	if (node->ancr_state == ws_active) {
+		/* Error, closed reference loop. */
+		printf("Error: Circular class, struct or interface chain: ");
+		ancr_csi_print_cycle(prog, node);
+		printf(".\n");
+		exit(1);
+	}
+
+	node->ancr_state = ws_active;
+
+	outer_csi = csi_to_symbol(node)->outer_csi;
+
+	/* Process outer CSI */
+	if (outer_csi != NULL)
+		ancr_csi_process(prog, outer_csi);
+
+	if (node->base_csi_ref != NULL) {
+		/* Resolve base CSI. */
+		base_sym = symbol_xlookup_in_csi(prog, outer_csi,
+			node->base_csi_ref);
+		base_csi = symbol_to_csi(base_sym);
+		assert(base_csi != NULL);
+
+		/* Process base CSI. */
+		ancr_csi_process(prog, base_csi);
+	}
+
+	node->ancr_state = ws_visited;
+}
+
+/** Print loop in CSI ancestry.
+ *
+ * We have detected a loop in CSI ancestry. Traverse it (by following the
+ * nodes in ws_active state and print it.
+ */
+static void ancr_csi_print_cycle(stree_program_t *prog, stree_csi_t *node)
+{
+	stree_csi_t *n;
+	stree_symbol_t *base_sym, *node_sym;
+	stree_csi_t *base_csi, *outer_csi;
+
+	n = node;
+	do {
+		node_sym = csi_to_symbol(node);
+		symbol_print_fqn(prog, node_sym);
+		printf(", ");
+
+		outer_csi = node_sym->outer_csi;
+
+		if (outer_csi != NULL && outer_csi->ancr_state == ws_active) {
+			node = outer_csi;
+		} else if (node->base_csi_ref != NULL) {
+			/* Resolve base CSI. */
+			base_sym = symbol_xlookup_in_csi(prog, outer_csi,
+				node->base_csi_ref);
+			base_csi = symbol_to_csi(base_sym);
+			assert(base_csi != NULL);
+
+			assert(base_csi->ancr_state == ws_active);
+			node = base_csi;
+		} else {
+			assert(b_false);
+		}
+	} while (n != node);
+
+	node_sym = csi_to_symbol(node);
+	symbol_print_fqn(prog, node_sym);
+}
Index: uspace/app/sbi/src/ancr.h
===================================================================
--- uspace/app/sbi/src/ancr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/ancr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANCR_H_
+#define ANCR_H_
+
+#include "mytypes.h"
+
+void ancr_module_process(stree_program_t *prog, stree_module_t *module);
+
+#endif
Index: uspace/app/sbi/src/builtin.c
===================================================================
--- uspace/app/sbi/src/builtin.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/builtin.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Builtin functions. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "list.h"
+#include "mytypes.h"
+#include "run.h"
+#include "stree.h"
+#include "strtab.h"
+
+#include "builtin.h"
+
+static void builtin_write_line(run_t *run);
+
+static stree_symbol_t *bi_write_line;
+
+/** Declare builtin symbols in the program.
+ *
+ * Declares symbols that will be hooked to builtin interpreter functions.
+ */
+void builtin_declare(stree_program_t *program)
+{
+	stree_modm_t *modm;
+	stree_csi_t *csi;
+	stree_ident_t *ident;
+	stree_csimbr_t *csimbr;
+	stree_fun_t *fun;
+	stree_fun_arg_t *fun_arg;
+	stree_symbol_t *symbol;
+
+	ident = stree_ident_new();
+	ident->sid = strtab_get_sid("Builtin");
+
+	csi = stree_csi_new(csi_class);
+	csi->name = ident;
+	list_init(&csi->members);
+
+	modm = stree_modm_new(mc_csi);
+	modm->u.csi = csi;
+
+	symbol = stree_symbol_new(sc_csi);
+	symbol->u.csi = csi;
+	symbol->outer_csi = NULL;
+	csi->symbol = symbol;
+
+	list_append(&program->module->members, modm);
+
+	/* Declare builtin functions. */
+	ident = stree_ident_new();
+	ident->sid = strtab_get_sid("WriteLine");
+
+	fun = stree_fun_new();
+	fun->name = ident;
+	fun->body = NULL;
+	list_init(&fun->args);
+
+	csimbr = stree_csimbr_new(csimbr_fun);
+	csimbr->u.fun = fun;
+
+	symbol = stree_symbol_new(sc_fun);
+	symbol->u.fun = fun;
+	symbol->outer_csi = csi;
+	fun->symbol = symbol;
+
+	list_append(&csi->members, csimbr);
+
+	fun_arg = stree_fun_arg_new();
+	fun_arg->name = stree_ident_new();
+	fun_arg->name->sid = strtab_get_sid("arg");
+	fun_arg->type = NULL; /* XXX */
+
+	list_append(&fun->args, fun_arg);
+
+	bi_write_line = symbol;
+}
+
+void builtin_run_fun(run_t *run, stree_symbol_t *fun_sym)
+{
+#ifdef DEBUG_RUN_TRACE
+	printf("Run builtin function.\n");
+#endif
+	if (fun_sym == bi_write_line) {
+		builtin_write_line(run);
+	} else {
+		assert(b_false);
+	}
+}
+
+static void builtin_write_line(run_t *run)
+{
+	rdata_var_t *var;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Called Builtin.writeLine()\n");
+#endif
+	var = run_local_vars_lookup(run, strtab_get_sid("arg"));
+	assert(var);
+
+	switch (var->vc) {
+	case vc_int:
+		printf("%d\n", var->u.int_v->value);
+		break;
+	case vc_string:
+		printf("%s\n", var->u.string_v->value);
+		break;
+	default:
+		printf("Unimplemented: writeLine() with unsupported type.\n");
+		exit(1);
+	}
+}
Index: uspace/app/sbi/src/builtin.h
===================================================================
--- uspace/app/sbi/src/builtin.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/builtin.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BUILTIN_H_
+#define BUILTIN_H_
+
+#include "mytypes.h"
+
+void builtin_declare(stree_program_t *program);
+void builtin_run_fun(run_t *run, stree_symbol_t *fun_sym);
+
+#endif
Index: uspace/app/sbi/src/compat.h
===================================================================
--- uspace/app/sbi/src/compat.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/compat.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file HelenOS compatibility hacks.
+ *
+ * This must be included later than HelenOS's list.h.
+ * XXX A better way must be found than this.
+ */
+
+#ifndef COMPAT_H_
+#define COMPAT_H_
+
+#ifdef __HELENOS__
+
+/*
+ * Avoid name conflicts with ADT library.
+ */
+#define list_append sbi_list_append
+#define list_prepend sbi_list_prepend
+#define list_remove sbi_list_remove
+
+/*
+ * These functions can be simply mapped to HelenOS string API.
+ */
+#define strcmp str_cmp
+#define strdup str_dup
+
+#endif
+
+#endif
Index: uspace/app/sbi/src/debug.h
===================================================================
--- uspace/app/sbi/src/debug.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/debug.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+/** Uncomment this to get verbose debugging messages during parsing. */
+//#define DEBUG_PARSE_TRACE
+
+/** Uncomment this to get verbose debugging messages during execution. */
+//#define DEBUG_RUN_TRACE
+
+#endif
Index: uspace/app/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/input.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Input module
+ *
+ * Reads source code from a file.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mytypes.h"
+#include "strtab.h"
+
+#include "input.h"
+
+#define INPUT_BUFFER_SIZE 256
+
+static int input_init(input_t *input, char *fname);
+
+/** Create new input object. */
+int input_new(input_t **input, char *fname)
+{
+	*input = malloc(sizeof(input_t));
+	if (*input == NULL)
+		return ENOMEM;
+
+	return input_init(*input, fname);
+}
+
+/** Initialize input object. */
+static int input_init(input_t *input, char *fname)
+{
+	FILE *f;
+
+	f = fopen(fname, "rt");
+	if (f == NULL)
+		return ENOENT;
+
+	input->buffer = malloc(INPUT_BUFFER_SIZE);
+	if (input->buffer == NULL)
+		return ENOMEM;
+
+	input->line_no = 0;
+	input->fin = f;
+	return EOK;
+}
+
+/** Get next line of input. */
+int input_get_line(input_t *input, char **line)
+{
+	if (fgets(input->buffer, INPUT_BUFFER_SIZE, input->fin) == NULL)
+		input->buffer[0] = '\0';
+
+	if (ferror(input->fin))
+		return EIO;
+
+	*line = input->buffer;
+	++input->line_no;
+	return EOK;
+}
+
+/** Get number of the last provided line of input. */
+int input_get_line_no(input_t *input)
+{
+	return input->line_no;
+}
Index: uspace/app/sbi/src/input.h
===================================================================
--- uspace/app/sbi/src/input.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/input.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INPUT_H_
+#define INPUT_H_
+
+#include "mytypes.h"
+
+int input_new(input_t **input, char *fname);
+int input_get_line(input_t *input, char **line);
+int input_get_line_no(input_t *input);
+
+#endif
Index: uspace/app/sbi/src/input_t.h
===================================================================
--- uspace/app/sbi/src/input_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/input_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INPUT_T_H_
+#define INPUT_T_H_
+
+#include <stdio.h>
+
+/** Input state object */
+typedef struct input {
+	/** Input file */
+	FILE *fin;
+
+	/** Buffer holding current line */
+	char *buffer;
+
+	/** Current line number */
+	int line_no;
+} input_t;
+
+#endif
Index: uspace/app/sbi/src/intmap.c
===================================================================
--- uspace/app/sbi/src/intmap.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/intmap.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Integer map.
+ *
+ * Maps integers to pointers (void *).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "list.h"
+#include "mytypes.h"
+
+#include "intmap.h"
+
+/** Initialize map. */
+void intmap_init(intmap_t *intmap)
+{
+	list_init(&intmap->elem);
+}
+
+/** Set value corresponding to a key. */
+void intmap_set(intmap_t *intmap, int key, void *value)
+{
+	list_node_t *node;
+	map_elem_t *elem;
+
+	node = list_first(&intmap->elem);
+	while (node != NULL) {
+		elem = list_node_data(node, map_elem_t *);
+		if (elem->key == key) {
+			if (value != NULL) {
+				/* Replace existing value. */
+				elem->value = value;
+			} else {
+				/* Remove map element. */
+				list_remove(&intmap->elem, node);
+				node->data = NULL;
+				free(node);
+			}
+			return;
+		}
+		node = list_next(&intmap->elem, node);
+	}
+
+	/* Allocate new map element and add it to the list. */
+
+	elem = calloc(1, sizeof(map_elem_t));
+	if (elem == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	elem->key = key;
+	elem->value = value;
+	list_append(&intmap->elem, elem);
+}
+
+/** Get value corresponding to a key. */
+void *intmap_get(intmap_t *intmap, int key)
+{
+	list_node_t *node;
+	map_elem_t *elem;
+
+	node = list_first(&intmap->elem);
+	while (node != NULL) {
+		elem = list_node_data(node, map_elem_t *);
+		if (elem->key == key) {
+			return elem->value;
+		}
+		node = list_next(&intmap->elem, node);
+	}
+
+	/* Not found */
+	return NULL;
+}
Index: uspace/app/sbi/src/intmap.h
===================================================================
--- uspace/app/sbi/src/intmap.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/intmap.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INTMAP_H_
+#define INTMAP_H_
+
+#include "mytypes.h"
+
+void intmap_init(intmap_t *intmap);
+void intmap_set(intmap_t *intmap, int key, void *data);
+void *intmap_get(intmap_t *intmap, int key);
+
+#endif
Index: uspace/app/sbi/src/intmap_t.h
===================================================================
--- uspace/app/sbi/src/intmap_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/intmap_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INTMAP_T_H_
+#define INTMAP_T_H_
+
+#include "list_t.h"
+
+typedef struct {
+	int key;
+	void *value;
+} map_elem_t;
+
+typedef struct intmap {
+	list_t elem; /* of (map_elem_t *) */
+} intmap_t;
+
+#endif
Index: uspace/app/sbi/src/lex.c
===================================================================
--- uspace/app/sbi/src/lex.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/lex.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Lexer (lexical analyzer).
+ *
+ * Consumes a text file and produces a sequence of lexical elements (lems).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "compat.h"
+#include "mytypes.h"
+#include "input.h"
+#include "strtab.h"
+
+#include "lex.h"
+
+#define TAB_WIDTH 8
+
+static void lex_skip_ws(lex_t *lex);
+static bool_t is_wstart(char c);
+static bool_t is_wcont(char c);
+static bool_t is_digit(char c);
+static void lex_word(lex_t *lex);
+static void lex_number(lex_t *lex);
+static void lex_string(lex_t *lex);
+static int digit_value(char c);
+
+/* Note: This imposes an implementation limit on identifier length. */
+#define IBUF_SIZE 128
+static char ident_buf[IBUF_SIZE + 1];
+
+/* XXX This imposes an implementation limit on string literal length. */
+#define SLBUF_SIZE 128
+static char strlit_buf[SLBUF_SIZE + 1];
+
+/** Lclass-string pair */
+struct lc_name {
+	lclass_t lclass;
+	const char *name;
+};
+
+/** Keyword names. Used both for printing and recognition. */
+static struct lc_name keywords[] = {
+	{ lc_class,	"class" },
+	{ lc_constructor,	"constructor" },
+	{ lc_do,	"do" },
+	{ lc_else,	"else" },
+	{ lc_end,	"end" },
+	{ lc_except,	"except" },
+	{ lc_finally,	"finally" },
+	{ lc_for,	"for" },
+	{ lc_fun,	"fun" },
+	{ lc_new,	"new" },
+	{ lc_get,	"get" },
+	{ lc_if,	"if" },
+	{ lc_in,	"in" },
+	{ lc_int,	"int" },
+	{ lc_interface,	"interface" },
+	{ lc_is,	"is" },
+	{ lc_override,	"override" },
+	{ lc_private,	"private" },
+	{ lc_prop,	"prop" },
+	{ lc_protected,	"protected" },
+	{ lc_public,	"public" },
+	{ lc_raise,	"raise" },
+	{ lc_return,	"return" },
+	{ lc_set,	"set" },
+	{ lc_static,	"static" },
+	{ lc_string,	"string" },
+	{ lc_struct,	"struct" },
+	{ lc_then,	"then" },
+	{ lc_this,	"this" },
+	{ lc_var,	"var" },
+	{ lc_with,	"with" },
+	{ lc_while,	"while" },
+	{ lc_yield,	"yield" },
+
+	{ 0,		NULL }
+};
+
+/** Other simple lclasses. Only used for printing. */
+static struct lc_name simple_lc[] = {
+	{ lc_invalid,	"INVALID" },
+	{ lc_eof,	"EOF" },
+
+	/* Operators */
+	{ lc_period,	"." },
+	{ lc_slash,	"/" },
+	{ lc_lparen,	"(" },
+	{ lc_rparen,	")" },
+	{ lc_lsbr,	"[" },
+	{ lc_rsbr,	"]" },
+	{ lc_equal,	"==" },
+	{ lc_notequal,	"!=" },
+	{ lc_lt,	"<" },
+	{ lc_gt,	">" },
+	{ lc_lt_equal,	"<=" },
+	{ lc_gt_equal,	">=" },
+	{ lc_assign,	"=" },
+	{ lc_plus,	"+" },
+	{ lc_increase,	"+=" },
+
+	/* Punctuators */
+	{ lc_comma,	"," },
+	{ lc_colon,	":" },
+	{ lc_scolon,	";" },
+
+	{ 0,		NULL },
+};
+
+/** Print lclass value. */
+void lclass_print(lclass_t lclass)
+{
+	struct lc_name *dp;
+
+	dp = keywords;
+	while (dp->name != NULL) {
+		if (dp->lclass == lclass) {
+			printf("%s", dp->name);
+			return;
+		}
+		++dp;
+	}
+
+	dp = simple_lc;
+	while (dp->name != NULL) {
+		if (dp->lclass == lclass) {
+			printf("%s", dp->name);
+			return;
+		}
+		++dp;
+	}
+
+	switch (lclass) {
+	case lc_ident:
+		printf("ident");
+		break;
+	case lc_lit_int:
+		printf("int_literal");
+		break;
+	case lc_lit_string:
+		printf("string_literal");
+		break;
+	default:
+		printf("<unknown?>");
+		break;
+	}
+}
+
+/** Print lexical element. */
+void lem_print(lem_t *lem)
+{
+	lclass_print(lem->lclass);
+
+	switch (lem->lclass) {
+	case lc_ident:
+		printf("(%d)", lem->u.ident.sid);
+		break;
+	case lc_lit_int:
+		printf("(%d)", lem->u.lit_int.value);
+		break;
+	case lc_lit_string:
+		printf("(\"%s\")", lem->u.lit_string.value);
+	default:
+		break;
+	}
+}
+
+/** Print lem coordinates. */
+void lem_print_coords(lem_t *lem)
+{
+	printf("%d:%d", lem->line_no, lem->col_0);
+}
+
+/** Initialize lexer instance. */
+void lex_init(lex_t *lex, struct input *input)
+{
+	int rc;
+
+	lex->input = input;
+
+	rc = input_get_line(lex->input, &lex->inbuf);
+	if (rc != EOK) {
+		printf("Error reading input.\n");
+		exit(1);
+	}
+
+	lex->ibp = lex->inbuf;
+	lex->col_adj = 0;
+}
+
+/** Read next lexical element. */
+void lex_next(lex_t *lex)
+{
+	char *bp;
+
+	lex_skip_ws(lex);
+
+	/*
+	 * Record lem coordinates. Line number we already have. For column
+	 * number we start with position in the input buffer. This works
+	 * for all characters except tab. Thus we keep track of tabs
+	 * separately using col_adj.
+	 */
+	lex->current.line_no = input_get_line_no(lex->input);
+	lex->current.col_0 = 1 + lex->col_adj + (lex->ibp - lex->inbuf);
+
+	bp = lex->ibp;
+
+	if (bp[0] == '\0') {
+		/* End of input */
+		lex->current.lclass = lc_eof;
+		return;
+	}
+
+	if (is_wstart(bp[0])) {
+		lex_word(lex);
+		return;
+	}
+
+	if (is_digit(bp[0])) {
+		lex_number(lex);
+		return;
+	}
+
+	if (bp[0] == '"') {
+		lex_string(lex);
+		return;
+	}
+
+	switch (bp[0]) {
+	case ',': lex->current.lclass = lc_comma; ++bp; break;
+	case ':': lex->current.lclass = lc_colon; ++bp; break;
+	case ';': lex->current.lclass = lc_scolon; ++bp; break;
+
+	case '.': lex->current.lclass = lc_period; ++bp; break;
+	case '/': lex->current.lclass = lc_slash; ++bp; break;
+	case '(': lex->current.lclass = lc_lparen; ++bp; break;
+	case ')': lex->current.lclass = lc_rparen; ++bp; break;
+	case '[': lex->current.lclass = lc_lsbr; ++bp; break;
+	case ']': lex->current.lclass = lc_rsbr; ++bp; break;
+
+	case '=':
+		if (bp[1] == '=') {
+			lex->current.lclass = lc_equal; bp += 2; break;
+		}
+		lex->current.lclass = lc_assign; ++bp; break;
+
+	case '!':
+		if (bp[1] == '=') {
+			lex->current.lclass = lc_notequal; bp += 2; break;
+		}
+		goto invalid;
+
+	case '+':
+		if (bp[1] == '=') {
+			lex->current.lclass = lc_increase; bp += 2; break;
+		}
+		lex->current.lclass = lc_plus; ++bp; break;
+
+	case '<':
+		if (bp[1] == '=') {
+			lex->current.lclass = lc_lt_equal; bp += 2; break;
+		}
+		lex->current.lclass = lc_lt; ++bp; break;
+
+	case '>':
+		if (bp[1] == '=') {
+			lex->current.lclass = lc_gt_equal; bp += 2; break;
+		}
+		lex->current.lclass = lc_gt; ++bp; break;
+
+	default:
+		goto invalid;
+	}
+
+	lex->ibp = bp;
+	return;
+
+invalid:
+	lex->current.lclass = lc_invalid;
+	++bp;
+	lex->ibp = bp;
+}
+
+/** Lex a word (identifier or keyword). */
+static void lex_word(lex_t *lex)
+{
+	struct lc_name *dp;
+	char *bp;
+	int idx;
+
+	bp = lex->ibp;
+	ident_buf[0] = bp[0];
+	idx = 1;
+
+	while (is_wcont(bp[idx])) {
+		if (idx >= IBUF_SIZE) {
+			printf("Error: Identifier too long.\n");
+			exit(1);
+		}
+
+		ident_buf[idx] = bp[idx];
+		++idx;
+	}
+
+	lex->ibp = bp + idx;
+
+	ident_buf[idx] = '\0';
+
+	dp = keywords;
+	while (dp->name != NULL) {
+		if (strcmp(ident_buf, dp->name) == 0) {
+			/* Match */
+			lex->current.lclass = dp->lclass;
+			return;
+		}
+		++dp;
+	}
+
+	/* No matching keyword -- it must be an identifier. */
+	lex->current.lclass = lc_ident;
+	lex->current.u.ident.sid = strtab_get_sid(ident_buf);
+}
+
+/** Lex a numeric literal. */
+static void lex_number(lex_t *lex)
+{
+	char *bp;
+	int value;
+
+	bp = lex->ibp;
+	value = 0;
+
+	while (is_digit(*bp)) {
+		value = value * 10 + digit_value(*bp);
+		++bp;
+	}
+
+	lex->ibp = bp;
+
+	lex->current.lclass = lc_lit_int;
+	lex->current.u.lit_int.value = value;
+}
+
+/** Lex a string literal. */
+static void lex_string(lex_t *lex)
+{
+	char *bp;
+	int idx;
+
+	bp = lex->ibp + 1;
+	idx = 0;
+
+	while (bp[idx] != '"') {
+		if (idx >= SLBUF_SIZE) {
+			printf("Error: String literal too long.\n");
+			exit(1);
+		}
+
+		if (bp[idx] == '\0') {
+			printf("Error: Unterminated string literal.\n");
+			exit(1);
+		}
+
+		strlit_buf[idx] = bp[idx];
+		++idx;
+	}
+
+	lex->ibp = bp + idx + 1;
+
+	strlit_buf[idx] = '\0';
+
+	lex->current.lclass = lc_lit_string;
+	lex->current.u.lit_string.value = strdup(strlit_buf);
+}
+
+
+/** Skip whitespace characters. */
+static void lex_skip_ws(lex_t *lex)
+{
+	char *bp;
+	int rc;
+
+	bp = lex->ibp;
+
+	while (b_true) {
+		while (*bp == ' ' || *bp == '\t') {
+			if (*bp == '\t')
+				lex->col_adj += (TAB_WIDTH - 1);
+			++bp;
+		}
+
+		if (*bp != '\n')
+			break;
+
+		/* Read next line */
+		rc = input_get_line(lex->input, &lex->inbuf);
+		if (rc != EOK) {
+			printf("Error reading input.\n");
+			exit(1);
+		}
+
+		bp = lex->inbuf;
+		lex->col_adj = 0;
+	}
+
+	lex->ibp = bp;
+}
+
+/** Determine if character can start a word. */
+static bool_t is_wstart(char c)
+{
+	return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ||
+	    (c == '_');
+}
+
+/** Determine if character can continue a word. */
+static bool_t is_wcont(char c)
+{
+	return is_digit(c) || is_wstart(c);
+}
+
+static bool_t is_digit(char c)
+{
+	return ((c >= '0') && (c <= '9'));
+}
+
+static int digit_value(char c)
+{
+	return (c - '0');
+}
Index: uspace/app/sbi/src/lex.h
===================================================================
--- uspace/app/sbi/src/lex.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/lex.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LEX_H_
+#define LEX_H_
+
+#include "mytypes.h"
+
+void lclass_print(lclass_t lclass);
+void lem_print(lem_t *lem);
+void lem_print_coords(lem_t *lem);
+
+void lex_init(lex_t *lex, struct input *input);
+void lex_next(lex_t *lex);
+
+#endif
Index: uspace/app/sbi/src/lex_t.h
===================================================================
--- uspace/app/sbi/src/lex_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/lex_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LEX_T_H_
+#define LEX_T_H_
+
+/** Lexical element class */
+typedef enum {
+	lc_invalid,
+	lc_eof,
+
+	lc_ident,
+	lc_lit_int,
+	lc_lit_string,
+
+	/* Keywords */
+	lc_class,
+	lc_constructor,
+	lc_do,
+	lc_else,
+	lc_end,
+	lc_except,
+	lc_finally,
+	lc_for,
+	lc_fun,
+	lc_new,
+	lc_get,
+	lc_if,
+	lc_in,
+	lc_int,
+	lc_interface,
+	lc_is,
+	lc_override,
+	lc_private,
+	lc_prop,
+	lc_protected,
+	lc_public,
+	lc_raise,
+	lc_return,
+	lc_set,
+	lc_static,
+	lc_string,
+	lc_struct,
+	lc_then,
+	lc_this,
+	lc_var,
+	lc_with,
+	lc_while,
+	lc_yield,
+
+	/* Operators */
+	lc_period,
+	lc_slash,
+	lc_lparen,
+	lc_rparen,
+	lc_lsbr,
+	lc_rsbr,
+	lc_equal,
+	lc_notequal,
+	lc_lt,
+	lc_gt,
+	lc_lt_equal,
+	lc_gt_equal,
+	lc_assign,
+	lc_plus,
+	lc_increase,
+
+	/* Punctuators */
+	lc_comma,
+	lc_colon,
+	lc_scolon,
+
+	lc__limit
+} lclass_t;
+
+typedef struct {
+	/* String ID */
+	int sid;
+} lem_ident_t;
+
+typedef struct {
+	/* Integer value */
+	int value;
+} lem_lit_int_t;
+
+typedef struct {
+	/* String value */
+	char *value;
+} lem_lit_string_t;
+
+/** Lexical element */
+typedef struct {
+	/* Lexical element class */
+	lclass_t lclass;
+
+	union {
+		lem_ident_t ident;
+		lem_lit_int_t lit_int;
+		lem_lit_string_t lit_string;
+	} u;
+
+	/** Coordinates of this lexical element */
+	int line_no, col_0;
+} lem_t;
+
+/** Lexer state object */
+typedef struct lex {
+	/** Input object */
+	struct input *input;
+
+	/** Lexing buffer */
+	char *inbuf;
+
+	/** Pointer to current position in lexing buffer */
+	char *ibp;
+
+	/** Number of the line currently in inbuf */
+	int ib_line;
+
+	/** Column number adjustment (due to tabs) */
+	int col_adj;
+
+	/** Curent lem */
+	lem_t current;
+} lex_t;
+
+#endif
Index: uspace/app/sbi/src/list.c
===================================================================
--- uspace/app/sbi/src/list.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/list.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Doubly linked list.
+ *
+ * Circular, with a head. Nodes structures are allocated separately from data.
+ * Data is stored as 'void *'. We implement several sanity checks to prevent
+ * common usage errors.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "mytypes.h"
+
+#include "list.h"
+
+static list_node_t *list_node_new(void *data);
+static void list_node_delete(list_node_t *node);
+static void list_node_insert_between(list_node_t *n, list_node_t *a, list_node_t *b);
+static void list_node_unlink(list_node_t *n);
+static bool_t list_node_present(list_t *list, list_node_t *node);
+
+/** Initialize list. */
+void list_init(list_t *list)
+{
+	list->head.prev = &list->head;
+	list->head.next = &list->head;
+}
+
+/** Append data to list. */
+void list_append(list_t *list, void *data)
+{
+	list_node_t *node;
+
+	node = list_node_new(data);
+	list_node_insert_between(node, list->head.prev, &list->head);
+}
+
+/** Prepend data to list. */
+void list_prepend(list_t *list, void *data)
+{
+	list_node_t *node;
+
+	node = list_node_new(data);
+	list_node_insert_between(node, list->head.prev, &list->head);
+}
+
+/** Remove data from list. */
+void list_remove(list_t *list, list_node_t *node)
+{
+	/* Check whether node is in the list as claimed. */
+	assert(list_node_present(list, node));
+	list_node_unlink(node);
+	node->data = NULL;
+	list_node_delete(node);
+}
+
+/** Return first list node or NULL if list is empty. */
+list_node_t *list_first(list_t *list)
+{
+	list_node_t *node;
+
+	assert(list != NULL);
+	node = list->head.next;
+
+	return (node != &list->head) ? node : NULL;
+}
+
+/** Return last list node or NULL if list is empty. */
+list_node_t *list_last(list_t *list)
+{
+	list_node_t *node;
+
+	assert(list != NULL);
+	node = list->head.prev;
+
+	return (node != &list->head) ? node : NULL;
+}
+
+/** Return next list node or NULL if this was the last one. */
+list_node_t *list_next(list_t *list, list_node_t *node)
+{
+	(void) list;
+	assert(list != NULL);
+	assert(node != NULL);
+
+	return (node->next != &list->head) ? node->next : NULL;
+}
+
+/** Return next list node or NULL if this was the last one. */
+list_node_t *list_prev(list_t *list, list_node_t *node)
+{
+	(void) list;
+	assert(list != NULL);
+	assert(node != NULL);
+
+	return (node->prev != &list->head) ? node->prev : NULL;
+}
+
+/** Return b_true if list is empty. */
+bool_t list_is_empty(list_t *list)
+{
+	return (list_first(list) == NULL);
+}
+
+/** Create new node. */
+static list_node_t *list_node_new(void *data)
+{
+	list_node_t *node;
+
+	node = malloc(sizeof(list_node_t));
+	if (node == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	node->prev = NULL;
+	node->next = NULL;
+	node->data = data;
+
+	return node;
+}
+
+/** Delete node. */
+static void list_node_delete(list_node_t *node)
+{
+	assert(node->prev == NULL);
+	assert(node->next == NULL);
+	assert(node->data == NULL);
+	free(node);
+}
+
+/** Insert node between two other nodes. */
+static void list_node_insert_between(list_node_t *n, list_node_t *a, list_node_t *b)
+{
+	assert(n->prev == NULL);
+	assert(n->next == NULL);
+	n->prev = a;
+	n->next = b;
+
+	assert(a->next == b);
+	assert(b->prev == a);
+	a->next = n;
+	b->prev = n;
+}
+
+/** Unlink node. */
+static void list_node_unlink(list_node_t *n)
+{
+	list_node_t *a, *b;
+	assert(n->prev != NULL);
+	assert(n->next != NULL);
+
+	a = n->prev;
+	b = n->next;
+
+	assert(a->next == n);
+	assert(b->prev == n);
+
+	a->next = b;
+	b->prev = a;
+
+	n->prev = NULL;
+	n->next = NULL;
+}
+
+/** Check whether @a node is in list @a list. */
+static bool_t list_node_present(list_t *list, list_node_t *node)
+{
+	list_node_t *m;
+
+	m = list->head.next;
+	while (m != &list->head) {
+		if (m == node)
+			return b_true;
+		m = m->next;
+	}
+
+	return b_false;
+}
Index: uspace/app/sbi/src/list.h
===================================================================
--- uspace/app/sbi/src/list.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/list.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIST_H_
+#define LIST_H_
+
+#include "mytypes.h"
+#include "compat.h"
+
+void list_init(list_t *list);
+void list_append(list_t *list, void *data);
+void list_prepend(list_t *list, void *data);
+void list_remove(list_t *list, list_node_t *node);
+
+list_node_t *list_first(list_t *list);
+list_node_t *list_last(list_t *list);
+list_node_t *list_next(list_t *list, list_node_t *node);
+list_node_t *list_prev(list_t *list, list_node_t *node);
+bool_t list_is_empty(list_t *list);
+
+#define list_node_data(node, dtype) ((dtype)(node->data))
+
+#endif
Index: uspace/app/sbi/src/list_t.h
===================================================================
--- uspace/app/sbi/src/list_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/list_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIST_T_H_
+#define LIST_T_H_
+
+typedef struct list_node {
+	struct list_node *prev, *next;
+	void *data;
+} list_node_t;
+
+typedef struct list {
+	/** Empty head (no data) */
+	list_node_t head;
+} list_t;
+
+#endif
Index: uspace/app/sbi/src/main.c
===================================================================
--- uspace/app/sbi/src/main.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/main.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Main module. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "ancr.h"
+#include "builtin.h"
+#include "mytypes.h"
+#include "strtab.h"
+#include "stree.h"
+#include "input.h"
+#include "lex.h"
+#include "parse.h"
+#include "run.h"
+
+void syntax_print(void);
+
+int main(int argc, char *argv[])
+{
+	input_t *input;
+	lex_t lex;
+	parse_t parse;
+	stree_program_t *program;
+	run_t run;
+	int rc;
+
+	if (argc != 2) {
+		syntax_print();
+		exit(1);
+	}
+
+	rc = input_new(&input, argv[1]);
+	if (rc != EOK) {
+		printf("Failed initializing input.\n");
+		exit(1);
+	}
+
+	strtab_init();
+	program = stree_program_new();
+	program->module = stree_module_new();
+
+	/* Declare builtin symbols. */
+	builtin_declare(program);
+
+	/* Parse input file. */
+	lex_init(&lex, input);
+	parse_init(&parse, program, &lex);
+	parse_module(&parse);
+
+	/* Resolve ancestry. */
+	ancr_module_process(program, parse.cur_mod);
+
+	/* Run program. */
+	run_init(&run);
+	run_program(&run, program);
+
+	return 0;
+}
+
+void syntax_print(void)
+{
+	printf("Missing or invalid arguments.\n");
+	printf("Syntax: sbi <source_file.sy>\n");
+}
Index: uspace/app/sbi/src/mytypes.h
===================================================================
--- uspace/app/sbi/src/mytypes.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/mytypes.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MYTYPES_H_
+#define MYTYPES_H_
+
+/** Boolean type compatible with builtin C 'boolean' operators. */
+typedef enum {
+	b_false = 0,
+	b_true = 1
+} bool_t;
+
+/** Node state for walks. */
+typedef enum {
+	ws_unvisited,
+	ws_active,
+	ws_visited
+} walk_state_t;
+
+/** Error return codes. */
+#include <errno.h>
+#define EOK 0
+
+#include "input_t.h"
+#include "intmap_t.h"
+#include "lex_t.h"
+#include "list_t.h"
+#include "parse_t.h"
+#include "rdata_t.h"
+#include "run_t.h"
+#include "stree_t.h"
+#include "strtab_t.h"
+
+#endif
Index: uspace/app/sbi/src/p_expr.c
===================================================================
--- uspace/app/sbi/src/p_expr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/p_expr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Parse arithmetic expressions. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "lex.h"
+#include "list.h"
+#include "mytypes.h"
+#include "parse.h"
+#include "stree.h"
+
+#include "p_expr.h"
+
+static stree_expr_t *parse_assign(parse_t *parse);
+static stree_expr_t *parse_comparative(parse_t *parse);
+static stree_expr_t *parse_additive(parse_t *parse);
+static stree_expr_t *parse_postfix(parse_t *parse);
+static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a);
+static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a);
+static stree_expr_t *parse_primitive(parse_t *parse);
+static stree_expr_t *parse_nameref(parse_t *parse);
+static stree_expr_t *parse_lit_int(parse_t *parse);
+static stree_expr_t *parse_lit_string(parse_t *parse);
+
+/** Parse expression. */
+stree_expr_t *parse_expr(parse_t *parse)
+{
+	return parse_assign(parse);
+}
+
+/** Parse assignment expression. */
+static stree_expr_t *parse_assign(parse_t *parse)
+{
+	stree_expr_t *a, *b, *tmp;
+	stree_assign_t *assign;
+
+	a = parse_comparative(parse);
+
+	switch (lcur_lc(parse)) {
+	case lc_assign:
+		assign = stree_assign_new(ac_set);
+		break;
+	case lc_increase:
+		assign = stree_assign_new(ac_increase);
+		break;
+	default:
+		return a;
+	}
+
+	lskip(parse);
+	b = parse_comparative(parse);
+
+	assign->dest = a;
+	assign->src = b;
+
+	tmp = stree_expr_new(ec_assign);
+	tmp->u.assign = assign;
+	return tmp;
+}
+
+/** Parse comparative expression. */
+static stree_expr_t *parse_comparative(parse_t *parse)
+{
+	stree_expr_t *a, *b, *tmp;
+	stree_binop_t *binop;
+	binop_class_t bc;
+
+	a = parse_additive(parse);
+
+	while (lcur_lc(parse) == lc_equal || lcur_lc(parse) == lc_notequal ||
+	    lcur_lc(parse) == lc_lt || lcur_lc(parse) == lc_gt ||
+	    lcur_lc(parse) == lc_lt_equal || lcur_lc(parse) == lc_gt_equal) {
+
+		switch (lcur_lc(parse)) {
+		case lc_equal: bc = bo_equal; break;
+		case lc_notequal: bc = bo_notequal; break;
+		case lc_lt: bc = bo_lt; break;
+		case lc_gt: bc = bo_gt; break;
+		case lc_lt_equal: bc = bo_lt_equal; break;
+		case lc_gt_equal: bc = bo_gt_equal; break;
+		default: assert(b_false);
+		}
+
+		lskip(parse);
+		b = parse_additive(parse);
+
+		binop = stree_binop_new(bc);
+		binop->arg1 = a;
+		binop->arg2 = b;
+
+		tmp = stree_expr_new(ec_binop);
+		tmp->u.binop = binop;
+		a = tmp;
+	}
+
+	return a;
+}
+
+/** Parse additive expression. */
+static stree_expr_t *parse_additive(parse_t *parse)
+{
+	stree_expr_t *a, *b, *tmp;
+	stree_binop_t *binop;
+
+	a = parse_postfix(parse);
+	while (lcur_lc(parse) == lc_plus) {
+		lskip(parse);
+		b = parse_postfix(parse);
+
+		binop = stree_binop_new(bo_plus);
+		binop->arg1 = a;
+		binop->arg2 = b;
+
+		tmp = stree_expr_new(ec_binop);
+		tmp->u.binop = binop;
+		a = tmp;
+	}
+
+	return a;
+}
+
+/** Parse postfix expression. */
+static stree_expr_t *parse_postfix(parse_t *parse)
+{
+	stree_expr_t *a;
+	stree_expr_t *tmp;
+
+	a = parse_primitive(parse);
+
+	while (lcur_lc(parse) == lc_period || lcur_lc(parse) == lc_lparen) {
+
+		switch (lcur_lc(parse)) {
+		case lc_period:
+			tmp = parse_pf_access(parse, a);
+			break;
+		case lc_lparen:
+			tmp = parse_pf_call(parse, a);
+			break;
+		default:
+			assert(b_false);
+		}
+
+		a = tmp;
+	}
+
+	return a;
+}
+
+/** Parse member access expression */
+static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a)
+{
+	stree_ident_t *ident;
+	stree_expr_t *expr;
+	stree_access_t *access;
+
+	lmatch(parse, lc_period);
+	ident = parse_ident(parse);
+
+	access = stree_access_new();
+	access->arg = a;
+	access->member_name = ident;
+
+	expr = stree_expr_new(ec_access);
+	expr->u.access = access;
+
+	return expr;
+}
+
+/** Parse function call expression. */
+static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a)
+{
+	stree_expr_t *expr;
+	stree_call_t *call;
+	stree_expr_t *arg;
+
+	lmatch(parse, lc_lparen);
+
+	call = stree_call_new();
+	call->fun = a;
+	list_init(&call->args);
+
+	/* Parse function arguments */
+
+	if (lcur_lc(parse) != lc_rparen) {
+		while (b_true) {
+			arg = parse_expr(parse);
+			list_append(&call->args, arg);
+
+			if (lcur_lc(parse) == lc_rparen)
+				break;
+			lmatch(parse, lc_comma);
+		}
+	}
+
+	lmatch(parse, lc_rparen);
+
+	expr = stree_expr_new(ec_call);
+	expr->u.call = call;
+
+	return expr;
+}
+
+/** Parse primitive expression. */
+static stree_expr_t *parse_primitive(parse_t *parse)
+{
+	stree_expr_t *expr;
+
+	switch (lcur_lc(parse)) {
+	case lc_ident:
+		expr = parse_nameref(parse);
+		break;
+	case lc_lit_int:
+		expr = parse_lit_int(parse);
+		break;
+	case lc_lit_string:
+		expr = parse_lit_string(parse);
+		break;
+	default:
+		lunexpected_error(parse);
+		exit(1);
+	}
+
+	return expr;
+}
+
+/** Parse name reference. */
+static stree_expr_t *parse_nameref(parse_t *parse)
+{
+	stree_nameref_t *nameref;
+	stree_expr_t *expr;
+
+	nameref = stree_nameref_new();
+	nameref->name = parse_ident(parse);
+	expr = stree_expr_new(ec_nameref);
+	expr->u.nameref = nameref;
+
+	return expr;
+}
+
+/** Parse integer literal. */
+static stree_expr_t *parse_lit_int(parse_t *parse)
+{
+	stree_literal_t *literal;
+	stree_expr_t *expr;
+
+	lcheck(parse, lc_lit_int);
+
+	literal = stree_literal_new(ltc_int);
+	literal->u.lit_int.value = lcur(parse)->u.lit_int.value;
+
+	lskip(parse);
+
+	expr = stree_expr_new(ec_literal);
+	expr->u.literal = literal;
+
+	return expr;
+}
+
+/** Parse string literal. */
+static stree_expr_t *parse_lit_string(parse_t *parse)
+{
+	stree_literal_t *literal;
+	stree_expr_t *expr;
+
+	lcheck(parse, lc_lit_string);
+
+	literal = stree_literal_new(ltc_string);
+	literal->u.lit_string.value = lcur(parse)->u.lit_string.value;
+
+	lskip(parse);
+
+	expr = stree_expr_new(ec_literal);
+	expr->u.literal = literal;
+
+	return expr;
+}
Index: uspace/app/sbi/src/p_expr.h
===================================================================
--- uspace/app/sbi/src/p_expr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/p_expr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef P_EXPR_H_
+#define P_EXPR_H_
+
+#include "mytypes.h"
+
+stree_expr_t *parse_expr(parse_t *parse);
+
+#endif
Index: uspace/app/sbi/src/p_type.c
===================================================================
--- uspace/app/sbi/src/p_type.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/p_type.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Parse arithmetic expressions. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "lex.h"
+#include "list.h"
+#include "mytypes.h"
+#include "parse.h"
+#include "stree.h"
+
+#include "p_type.h"
+
+static stree_texpr_t *parse_tapply(parse_t *parse);
+static stree_texpr_t *parse_tpostfix(parse_t *parse);
+static stree_texpr_t *parse_tprimitive(parse_t *parse);
+static stree_tnameref_t *parse_tnameref(parse_t *parse);
+
+/** Parse type expression. */
+stree_texpr_t *parse_texpr(parse_t *parse)
+{
+	return parse_tapply(parse);
+}
+
+/** Parse type application expression. */
+static stree_texpr_t *parse_tapply(parse_t *parse)
+{
+	stree_texpr_t *a, *b, *tmp;
+	stree_tapply_t *tapply;
+
+	a = parse_tpostfix(parse);
+	while (lcur_lc(parse) == lc_slash) {
+		lskip(parse);
+		b = parse_tpostfix(parse);
+
+		tapply = stree_tapply_new();
+		tapply->gtype = a;
+		tapply->targ = b;
+
+		tmp = stree_texpr_new(tc_tapply);
+		tmp->u.tapply = tapply;
+		a = tmp;
+	}
+
+	return a;
+}
+
+/** Parse postfix type expression. */
+static stree_texpr_t *parse_tpostfix(parse_t *parse)
+{
+	stree_texpr_t *a;
+	stree_ident_t *ident;
+	stree_texpr_t *tmp;
+	stree_taccess_t *taccess;
+
+	a = parse_tprimitive(parse);
+
+	while (lcur_lc(parse) == lc_period) {
+		lskip(parse);
+		ident = parse_ident(parse);
+
+		taccess = stree_taccess_new();
+		taccess->arg = a;
+		taccess->member_name = ident;
+
+		tmp = stree_texpr_new(tc_taccess);
+		tmp->u.taccess = taccess;
+		a = tmp;
+	}
+
+	return a;
+}
+
+/** Parse primitive type expression. */
+static stree_texpr_t *parse_tprimitive(parse_t *parse)
+{
+	stree_texpr_t *texpr;
+
+	lcheck(parse, lc_ident);
+	texpr = stree_texpr_new(tc_tnameref);
+	texpr->u.tnameref = parse_tnameref(parse);
+
+	return texpr;
+}
+
+/** Parse type identifier. */
+static stree_tnameref_t *parse_tnameref(parse_t *parse)
+{
+	stree_tnameref_t *tnameref;
+
+	tnameref = stree_tnameref_new();
+	tnameref->name = parse_ident(parse);
+
+	return tnameref;
+}
Index: uspace/app/sbi/src/p_type.h
===================================================================
--- uspace/app/sbi/src/p_type.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/p_type.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef P_TYPE_H_
+#define P_TYPE_H_
+
+#include "mytypes.h"
+
+stree_texpr_t *parse_texpr(parse_t *parse);
+
+#endif
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/parse.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Parser
+ *
+ * Consumes a sequence of lexical elements and produces a syntax tree (stree).
+ * Parsing primitives, module members, statements.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "lex.h"
+#include "list.h"
+#include "mytypes.h"
+#include "p_expr.h"
+#include "p_type.h"
+#include "stree.h"
+#include "strtab.h"
+
+#include "parse.h"
+
+/*
+ * Module members
+ */
+static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass);
+static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
+
+static stree_fun_t *parse_fun(parse_t *parse);
+static stree_var_t *parse_var(parse_t *parse);
+static stree_prop_t *parse_prop(parse_t *parse);
+
+static stree_fun_arg_t *parse_fun_arg(parse_t *parse);
+
+/*
+ * Statements
+ */
+static stree_block_t *parse_block(parse_t *parse);
+static stree_stat_t *parse_stat(parse_t *parse);
+
+static stree_vdecl_t *parse_vdecl(parse_t *parse);
+static stree_if_t *parse_if(parse_t *parse);
+static stree_while_t *parse_while(parse_t *parse);
+static stree_for_t *parse_for(parse_t *parse);
+static stree_raise_t *parse_raise(parse_t *parse);
+static stree_wef_t *parse_wef(parse_t *parse);
+static stree_exps_t *parse_exps(parse_t *parse);
+
+void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
+{
+	parse->program = prog;
+	parse->cur_mod = parse->program->module;
+	parse->lex = lex;
+	lex_next(parse->lex);
+}
+
+/** Parse module. */
+void parse_module(parse_t *parse)
+{
+	stree_csi_t *csi;
+	stree_modm_t *modm;
+	stree_symbol_t *symbol;
+
+/*	do {
+		lex_next(parse->lex);
+		printf("Read token: "); lem_print(&parse->lex->current);
+		putchar('\n');
+	} while (parse->lex->current.lclass != lc_eof);
+*/
+	while (lcur_lc(parse) != lc_eof) {
+		switch (lcur_lc(parse)) {
+		case lc_class:
+		case lc_struct:
+		case lc_interface:
+			csi = parse_csi(parse, lcur_lc(parse));
+			modm = stree_modm_new(mc_csi);
+			modm->u.csi = csi;
+
+			symbol = stree_symbol_new(sc_csi);
+			symbol->u.csi = csi;
+			symbol->outer_csi = NULL;
+			csi->symbol = symbol;
+
+			list_append(&parse->cur_mod->members, modm);
+			break;
+		default:
+			lunexpected_error(parse);
+			lex_next(parse->lex);
+			break;
+		}
+
+	}
+}
+
+/** Parse class, struct or interface declaration. */
+static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass)
+{
+	stree_csi_t *csi;
+	csi_class_t cc;
+	stree_csimbr_t *csimbr;
+
+	switch (dclass) {
+	case lc_class: cc = csi_class; break;
+	case lc_struct: cc = csi_struct; break;
+	case lc_interface: cc = csi_interface; break;
+	default: assert(b_false);
+	}
+
+	lskip(parse);
+
+	csi = stree_csi_new(cc);
+	csi->name = parse_ident(parse);
+/*
+	printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
+	    strtab_get_str(csi->name->sid));
+*/
+	if (lcur_lc(parse) == lc_colon) {
+		/* Inheritance list */
+		lskip(parse);
+		csi->base_csi_ref = parse_texpr(parse);
+	} else {
+		csi->base_csi_ref = NULL;
+	}
+
+	lmatch(parse, lc_is);
+	list_init(&csi->members);
+
+	/* Parse class, struct or interface members. */
+	while (lcur_lc(parse) != lc_end) {
+		csimbr = parse_csimbr(parse, csi);
+		list_append(&csi->members, csimbr);
+	}
+
+	lmatch(parse, lc_end);
+
+	return csi;
+}
+
+/** Parse class, struct or interface member. */
+static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
+{
+	stree_csimbr_t *csimbr;
+
+	stree_csi_t *csi;
+	stree_fun_t *fun;
+	stree_var_t *var;
+	stree_prop_t *prop;
+
+	stree_symbol_t *symbol;
+
+	switch (lcur_lc(parse)) {
+	case lc_class:
+	case lc_struct:
+	case lc_interface:
+		csi = parse_csi(parse, lcur_lc(parse));
+		csimbr = stree_csimbr_new(csimbr_csi);
+		csimbr->u.csi = csi;
+
+		symbol = stree_symbol_new(sc_csi);
+		symbol->u.csi = csi;
+		symbol->outer_csi = outer_csi;
+		csi->symbol = symbol;
+		break;
+	case lc_fun:
+		fun = parse_fun(parse);
+		csimbr = stree_csimbr_new(csimbr_fun);
+		csimbr->u.fun = fun;
+
+		symbol = stree_symbol_new(sc_fun);
+		symbol->u.fun = fun;
+		symbol->outer_csi = outer_csi;
+		fun->symbol = symbol;
+		break;
+	case lc_var:
+		var = parse_var(parse);
+		csimbr = stree_csimbr_new(csimbr_var);
+		csimbr->u.var = var;
+
+		symbol = stree_symbol_new(sc_var);
+		symbol->u.var = var;
+		symbol->outer_csi = outer_csi;
+		var->symbol = symbol;
+		break;
+	case lc_prop:
+		prop = parse_prop(parse);
+		csimbr = stree_csimbr_new(csimbr_prop);
+		csimbr->u.prop = prop;
+
+		symbol = stree_symbol_new(sc_prop);
+		symbol->u.prop = prop;
+		symbol->outer_csi = outer_csi;
+		prop->symbol = symbol;
+		break;
+	default:
+		lunexpected_error(parse);
+		lex_next(parse->lex);
+	}
+
+	return csimbr;
+}
+
+
+/** Parse member function. */
+static stree_fun_t *parse_fun(parse_t *parse)
+{
+	stree_fun_t *fun;
+	stree_fun_arg_t *arg;
+
+	fun = stree_fun_new();
+
+	lmatch(parse, lc_fun);
+	fun->name = parse_ident(parse);
+	lmatch(parse, lc_lparen);
+
+	list_init(&fun->args);
+
+	if (lcur_lc(parse) != lc_rparen) {
+
+		/* Parse formal parameters. */
+		while (b_true) {
+			arg = parse_fun_arg(parse);
+			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;
+	}
+
+	lmatch(parse, lc_is);
+	fun->body = parse_block(parse);
+	lmatch(parse, lc_end);
+
+	return fun;
+}
+
+/** Parse member variable. */
+static stree_var_t *parse_var(parse_t *parse)
+{
+	stree_var_t *var;
+
+	var = stree_var_new();
+
+	lmatch(parse, lc_var);
+	var->name = parse_ident(parse);
+	lmatch(parse, lc_colon);
+	var->type =  parse_texpr(parse);
+	lmatch(parse, lc_scolon);
+
+	return var;
+}
+
+/** Parse member property. */
+static stree_prop_t *parse_prop(parse_t *parse)
+{
+	stree_prop_t *prop;
+
+	prop = stree_prop_new();
+
+	lmatch(parse, lc_prop);
+	prop->name = parse_ident(parse);
+	lmatch(parse, lc_colon);
+	prop->type = parse_texpr(parse);
+	lmatch(parse, lc_is);
+	lmatch(parse, lc_end);
+
+	return prop;
+}
+
+/** Parse formal function argument. */
+static stree_fun_arg_t *parse_fun_arg(parse_t *parse)
+{
+	stree_fun_arg_t *arg;
+
+	arg = stree_fun_arg_new();
+	arg->name = parse_ident(parse);
+	lmatch(parse, lc_colon);
+	arg->type = parse_texpr(parse);
+
+	return arg;
+}
+
+/** Parse statement block. */
+static stree_block_t *parse_block(parse_t *parse)
+{
+	stree_block_t *block;
+	stree_stat_t *stat;
+
+	block = stree_block_new();
+	list_init(&block->stats);
+
+	while (terminates_block(lcur_lc(parse)) != b_true) {
+		stat = parse_stat(parse);
+		list_append(&block->stats, stat);
+	}
+
+	return block;
+}
+
+/** Parse statement. */
+static stree_stat_t *parse_stat(parse_t *parse)
+{
+	stree_stat_t *stat;
+
+	stree_vdecl_t *vdecl_s;
+	stree_if_t *if_s;
+	stree_while_t *while_s;
+	stree_for_t *for_s;
+	stree_raise_t *raise_s;
+	stree_wef_t *wef_s;
+	stree_exps_t *exp_s;
+
+	switch (lcur_lc(parse)) {
+	case lc_var:
+		vdecl_s = parse_vdecl(parse);
+		stat = stree_stat_new(st_vdecl);
+		stat->u.vdecl_s = vdecl_s;
+		break;
+	case lc_if:
+		if_s = parse_if(parse);
+		stat = stree_stat_new(st_if);
+		stat->u.if_s = if_s;
+		break;
+	case lc_while:
+		while_s = parse_while(parse);
+		stat = stree_stat_new(st_while);
+		stat->u.while_s = while_s;
+		break;
+	case lc_for:
+		for_s = parse_for(parse);
+		stat = stree_stat_new(st_for);
+		stat->u.for_s = for_s;
+		break;
+	case lc_raise:
+		raise_s = parse_raise(parse);
+		stat = stree_stat_new(st_raise);
+		stat->u.raise_s = raise_s;
+		break;
+	case lc_with:
+		wef_s = parse_wef(parse);
+		stat = stree_stat_new(st_wef);
+		stat->u.wef_s = wef_s;
+		break;
+	default:
+		exp_s = parse_exps(parse);
+		stat = stree_stat_new(st_exps);
+		stat->u.exp_s = exp_s;
+		break;
+	}
+
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parsed statement %p\n", stat);
+#endif
+	return stat;
+}
+
+/** Parse variable declaration statement. */
+static stree_vdecl_t *parse_vdecl(parse_t *parse)
+{
+	stree_vdecl_t *vdecl;
+
+	vdecl = stree_vdecl_new();
+
+	lmatch(parse, lc_var);
+	vdecl->name = parse_ident(parse);
+	lmatch(parse, lc_colon);
+	vdecl->type = parse_texpr(parse);
+
+	if (lcur_lc(parse) == lc_assign) {
+		lskip(parse);
+		(void) parse_expr(parse);
+	}
+
+	lmatch(parse, lc_scolon);
+
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
+	printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
+	    vdecl, vdecl->name, vdecl->name->sid);
+#endif
+	return vdecl;
+}
+
+/** Parse @c if statement, */
+static stree_if_t *parse_if(parse_t *parse)
+{
+	stree_if_t *if_s;
+
+	if_s = stree_if_new();
+
+	lmatch(parse, lc_if);
+	if_s->cond = parse_expr(parse);
+	lmatch(parse, lc_then);
+	if_s->if_block = parse_block(parse);
+
+	if (lcur_lc(parse) == lc_else) {
+		lskip(parse);
+		if_s->else_block = parse_block(parse);
+	} else {
+		if_s->else_block = NULL;
+	}
+
+	lmatch(parse, lc_end);
+	return if_s;
+}
+
+/** Parse @c while statement. */
+static stree_while_t *parse_while(parse_t *parse)
+{
+	stree_while_t *while_s;
+
+	while_s = stree_while_new();
+
+	lmatch(parse, lc_while);
+	while_s->cond = parse_expr(parse);
+	lmatch(parse, lc_do);
+	while_s->body = parse_block(parse);
+	lmatch(parse, lc_end);
+
+	return while_s;
+}
+
+/** Parse @c for statement. */
+static stree_for_t *parse_for(parse_t *parse)
+{
+	stree_for_t *for_s;
+
+	for_s = stree_for_new();
+
+	lmatch(parse, lc_for);
+	lmatch(parse, lc_ident);
+	lmatch(parse, lc_colon);
+	(void) parse_texpr(parse);
+	lmatch(parse, lc_in);
+	(void) parse_expr(parse);
+	lmatch(parse, lc_do);
+	for_s->body = parse_block(parse);
+	lmatch(parse, lc_end);
+
+	return for_s;
+}
+
+/** Parse @c raise statement. */
+static stree_raise_t *parse_raise(parse_t *parse)
+{
+	lmatch(parse, lc_raise);
+	(void) parse_expr(parse);
+	lmatch(parse, lc_scolon);
+
+	return stree_raise_new();
+}
+
+/* Parse @c with-except-finally statement. */
+static stree_wef_t *parse_wef(parse_t *parse)
+{
+	stree_wef_t *wef_s;
+	stree_block_t *block;
+
+	wef_s = stree_wef_new();
+	list_init(&wef_s->except_blocks);
+
+	lmatch(parse, lc_with);
+	lmatch(parse, lc_ident);
+	lmatch(parse, lc_colon);
+	(void) parse_texpr(parse);
+	lmatch(parse, lc_assign);
+	(void) parse_expr(parse);
+	lmatch(parse, lc_do);
+	wef_s->with_block = parse_block(parse);
+
+	while (lcur_lc(parse) == lc_except) {
+		lmatch(parse, lc_except);
+		lmatch(parse, lc_ident);
+		lmatch(parse, lc_colon);
+		(void) parse_texpr(parse);
+		lmatch(parse, lc_do);
+
+		block = parse_block(parse);
+		list_append(&wef_s->except_blocks, block);
+	}
+
+	lmatch(parse, lc_finally);
+	lmatch(parse, lc_do);
+	wef_s->finally_block = parse_block(parse);
+	lmatch(parse, lc_end);
+
+	return wef_s;
+}
+
+/* Parse expression statement. */
+static stree_exps_t *parse_exps(parse_t *parse)
+{
+	stree_expr_t *expr;
+	stree_exps_t *exps;
+
+	expr = parse_expr(parse);
+	lmatch(parse, lc_scolon);
+
+	exps = stree_exps_new();
+	exps->expr = expr;
+
+	return exps;
+}
+
+/** Parse identifier. */
+stree_ident_t *parse_ident(parse_t *parse)
+{
+	stree_ident_t *ident;
+
+	lcheck(parse, lc_ident);
+	ident = stree_ident_new();
+	ident->sid = lcur(parse)->u.ident.sid;
+	lskip(parse);
+
+	return ident;
+}
+
+/** Return current lem. */
+lem_t *lcur(parse_t *parse)
+{
+	return &parse->lex->current;
+}
+
+/** Retturn current lem lclass. */
+lclass_t lcur_lc(parse_t *parse)
+{
+	return parse->lex->current.lclass;
+}
+
+/** Skip to next lem. */
+void lskip(parse_t *parse)
+{
+	lex_next(parse->lex);
+}
+
+/** Verify that lclass of current lem is @a lc. */
+void lcheck(parse_t *parse, lclass_t lc)
+{
+	if (lcur(parse)->lclass != lc) {
+		lem_print_coords(lcur(parse));
+		printf(" Error: expected '"); lclass_print(lc);
+		printf("', got '"); lem_print(lcur(parse));
+		printf("'.\n");
+		exit(1);
+	}
+}
+
+/** Verify that lclass of current lem is @a lc and go to next lem. */
+void lmatch(parse_t *parse, lclass_t lc)
+{
+	lcheck(parse, lc);
+	lskip(parse);
+}
+
+/** Display generic parsing error. */
+void lunexpected_error(parse_t *parse)
+{
+	lem_print_coords(lcur(parse));
+	printf(" Error: unexpected token '");
+	lem_print(lcur(parse));
+	printf("'.\n");
+	exit(1);
+}
+
+/** Basically tells us whether @a lclass is in next(block). */
+bool_t terminates_block(lclass_t lclass)
+{
+	switch (lclass) {
+	case lc_else:
+	case lc_end:
+	case lc_except:
+	case lc_finally:
+		return b_true;
+	default:
+		return b_false;
+	}
+}
Index: uspace/app/sbi/src/parse.h
===================================================================
--- uspace/app/sbi/src/parse.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/parse.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PARSE_H_
+#define PARSE_H_
+
+#include "mytypes.h"
+
+void parse_init(parse_t *parse, struct stree_program *prog, struct lex *lex);
+void parse_module(parse_t *parse);
+
+stree_ident_t *parse_ident(parse_t *parse);
+
+/*
+ * Parsing primitives
+ */
+lem_t *lcur(parse_t *parse);
+lclass_t lcur_lc(parse_t *parse);
+void lskip(parse_t *parse);
+void lcheck(parse_t *parse, lclass_t lc);
+void lmatch(parse_t *parse, lclass_t lc);
+void lunexpected_error(parse_t *parse);
+
+bool_t terminates_block(lclass_t lclass);
+
+#endif
Index: uspace/app/sbi/src/parse_t.h
===================================================================
--- uspace/app/sbi/src/parse_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/parse_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PARSE_T_H_
+#define PARSE_T_H_
+
+/** Parser state object */
+typedef struct {
+	/** Lexer object */
+	struct lex *lex;
+
+	/** Program being parsed */
+	struct stree_program *program;
+
+	/** Module currently being parsed */
+	struct stree_module *cur_mod;
+} parse_t;
+
+#endif
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/rdata.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Run-time data representation. */
+
+#include <stdlib.h>
+#include <assert.h>
+#include "mytypes.h"
+
+#include "rdata.h"
+
+static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest);
+static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest);
+static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest);
+static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest);
+static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest);
+
+static void rdata_address_print(rdata_address_t *address);
+static void rdata_value_print(rdata_value_t *value);
+static void rdata_var_print(rdata_var_t *var);
+
+
+rdata_item_t *rdata_item_new(item_class_t ic)
+{
+	rdata_item_t *item;
+
+	item = calloc(1, sizeof(rdata_item_t));
+	if (item == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	item->ic = ic;
+	return item;
+}
+
+rdata_address_t *rdata_address_new(void)
+{
+	rdata_address_t *address;
+
+	address = calloc(1, sizeof(rdata_address_t));
+	if (address == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return address;
+}
+
+rdata_value_t *rdata_value_new(void)
+{
+	rdata_value_t *value;
+
+	value = calloc(1, sizeof(rdata_value_t));
+	if (value == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return value;
+}
+
+rdata_var_t *rdata_var_new(var_class_t vc)
+{
+	rdata_var_t *var;
+
+	var = calloc(1, sizeof(rdata_var_t));
+	if (var == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	var->vc = vc;
+	return var;
+}
+
+rdata_deleg_t *rdata_deleg_new(void)
+{
+	rdata_deleg_t *deleg;
+
+	deleg = calloc(1, sizeof(rdata_deleg_t));
+	if (deleg == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return deleg;
+}
+
+rdata_int_t *rdata_int_new(void)
+{
+	rdata_int_t *int_v;
+
+	int_v = calloc(1, sizeof(rdata_int_t));
+	if (int_v == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return int_v;
+}
+
+rdata_string_t *rdata_string_new(void)
+{
+	rdata_string_t *string_v;
+
+	string_v = calloc(1, sizeof(rdata_string_t));
+	if (string_v == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return string_v;
+}
+
+/** Make copy of a variable. */
+void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest)
+{
+	rdata_var_t *nvar;
+
+	nvar = rdata_var_new(src->vc);
+
+	switch (src->vc) {
+	case vc_int:
+		rdata_int_copy(src->u.int_v, &nvar->u.int_v);
+		break;
+	case vc_string:
+		rdata_string_copy(src->u.string_v, &nvar->u.string_v);
+		break;
+	case vc_ref:
+		rdata_ref_copy(src->u.ref_v, &nvar->u.ref_v);
+		break;
+	case vc_deleg:
+		rdata_deleg_copy(src->u.deleg_v, &nvar->u.deleg_v);
+		break;
+	case vc_object:
+		rdata_object_copy(src->u.object_v, &nvar->u.object_v);
+		break;
+	}
+
+	*dest = nvar;
+}
+
+static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest)
+{
+	*dest = rdata_int_new();
+	(*dest)->value = src->value;
+}
+
+static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest)
+{
+	*dest = rdata_string_new();
+	(*dest)->value = src->value;
+}
+
+static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest)
+{
+	printf("Unimplemented: Copy reference.\n");
+	exit(1);
+}
+
+static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest)
+{
+	printf("Unimplemented: Copy delegate.\n");
+	exit(1);
+}
+
+static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest)
+{
+	printf("Unimplemented: Copy object.\n");
+	exit(1);
+}
+
+void rdata_item_print(rdata_item_t *item)
+{
+	if (item == NULL) {
+		printf("none");
+		return;
+	}
+
+	switch (item->ic) {
+	case ic_address:
+		printf("address:");
+		rdata_address_print(item->u.address);
+		break;
+	case ic_value:
+		printf("value:");
+		rdata_value_print(item->u.value);
+		break;
+	}
+}
+
+static void rdata_address_print(rdata_address_t *address)
+{
+	rdata_var_print(address->vref);
+}
+
+static void rdata_value_print(rdata_value_t *value)
+{
+	rdata_var_print(value->var);
+}
+
+static void rdata_var_print(rdata_var_t *var)
+{
+	switch (var->vc) {
+	case vc_int:
+		printf("int(%d)", var->u.int_v->value);
+		break;
+	case vc_ref:
+		printf("ref");
+		break;
+	case vc_deleg:
+		printf("deleg");
+		break;
+	case vc_object:
+		printf("object");
+		break;
+	default:
+		assert(b_false);
+	}
+}
Index: uspace/app/sbi/src/rdata.h
===================================================================
--- uspace/app/sbi/src/rdata.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/rdata.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RDATA_H_
+#define RDATA_H_
+
+#include "mytypes.h"
+
+rdata_item_t *rdata_item_new(item_class_t ic);
+rdata_address_t *rdata_address_new(void);
+rdata_value_t *rdata_value_new(void);
+rdata_var_t *rdata_var_new(var_class_t vc);
+rdata_deleg_t *rdata_deleg_new(void);
+rdata_int_t *rdata_int_new(void);
+rdata_string_t *rdata_string_new(void);
+
+void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest);
+void rdata_item_print(rdata_item_t *item);
+
+#endif
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/rdata_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Run-time data representation. */
+
+
+#ifndef RDATA_T_H_
+#define RDATA_T_H_
+
+#include "intmap_t.h"
+
+/** Integer variable */
+typedef struct {
+	/*
+	 * Note: Sysel int type should be able to store arbitrarily large
+	 * numbers. But for now we can live with limited width.
+	 */
+	int value;
+} rdata_int_t;
+
+/** String variable */
+typedef struct {
+	char *value;
+} rdata_string_t;
+
+/** Reference variable */
+typedef struct {
+	struct rdata_var *vref;
+} rdata_ref_t;
+
+/** Delegate variable
+ *
+ * A delegate variable points to a static or non-static symbol. If the
+ * symbol is non static, @c obj points to the object the symbol instance
+ * belongs to.
+ */
+typedef struct {
+	/** Object or @c NULL if deleg. points to a CSI or static member. */
+	struct rdata_var *obj;
+
+	/** Member symbol. */
+	struct stree_symbol *sym;
+} rdata_deleg_t;
+
+/** Object variable */
+typedef struct {
+	/** Class of this object (symbol) */
+	struct stree_symbol *class_sym;
+
+	/** Map field name SID to field data */
+	intmap_t *fields; /* of (rdata_var_t *) */
+} rdata_object_t;
+
+typedef enum var_class {
+	/** Integer */
+	vc_int,
+
+	/** String */
+	vc_string,
+
+	/** Reference */
+	vc_ref,
+
+	/** Delegate */
+	vc_deleg,
+
+	/** Object */
+	vc_object
+} var_class_t;
+
+/** Variable.
+ *
+ * A piece of memory holding one of the basic types of data element.
+ * It is addressable (via rdata_var_t *) and mutable, at least from
+ * internal point of view of the interpreter.
+ */
+typedef struct rdata_var {
+	var_class_t vc;
+
+	union {
+		rdata_int_t *int_v;
+		rdata_string_t *string_v;
+		rdata_ref_t *ref_v;
+		rdata_deleg_t *deleg_v;
+		rdata_object_t *object_v;
+	} u;
+} rdata_var_t;
+
+/** Address item. */
+typedef struct {
+	/** Targeted variable */
+	rdata_var_t *vref;
+} rdata_address_t;
+
+/** Value item. */
+typedef struct {
+	/**
+	 * Read-only Variable holding a copy of the data. The same @c var
+	 * can be shared between different instances of @c rdata_value_t.
+	 */
+	rdata_var_t *var;
+} rdata_value_t;
+
+typedef enum {
+	/** Address of a variable. */
+	ic_address,
+	/** Value */
+	ic_value
+} item_class_t;
+
+/** Data item.
+ *
+ * Data item is the result of evaluating an expression. An address expression
+ * yields an address item (a.k.a. L-value), a value expression yields a data
+ * item (a.k.a. R-value). This model is used to accomodate semantics of the
+ * assignment operator.
+ */
+typedef struct {
+	item_class_t ic;
+
+	union {
+		rdata_address_t *address;
+		rdata_value_t *value;
+	} u;
+} rdata_item_t;
+
+#endif
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Runner (executes the code). */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "builtin.h"
+#include "debug.h"
+#include "intmap.h"
+#include "list.h"
+#include "mytypes.h"
+#include "rdata.h"
+#include "run_expr.h"
+#include "stree.h"
+#include "strtab.h"
+#include "symbol.h"
+
+#include "run.h"
+
+static void run_block(run_t *run, stree_block_t *block);
+static void run_stat(run_t *run, stree_stat_t *stat);
+static void run_exps(run_t *run, stree_exps_t *exps);
+static void run_vdecl(run_t *run, stree_vdecl_t *vdecl);
+static void run_if(run_t *run, stree_if_t *if_s);
+static void run_while(run_t *run, stree_while_t *while_s);
+
+static void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var);
+
+/** Initialize runner instance. */
+void run_init(run_t *run)
+{
+}
+
+/** Run program */
+void run_program(run_t *run, stree_program_t *prog)
+{
+	stree_symbol_t *main_class_sym;
+	stree_symbol_t *main_fun_sym;
+	stree_csi_t *main_class;
+	stree_fun_t *main_fun;
+	stree_ident_t *fake_ident;
+	list_t main_args;
+
+	/* Note down link to program code. */
+	run->program = prog;
+
+	/* Initialize thread activation record. */
+	run->thread_ar = run_thread_ar_new();
+	list_init(&run->thread_ar->fun_ar);
+
+	/*
+	 * Resolve class @c HelloWorld
+	 */
+	fake_ident = stree_ident_new();
+
+	fake_ident->sid = strtab_get_sid("HelloWorld");
+	main_class_sym = symbol_lookup_in_csi(prog, NULL, fake_ident);
+	main_class = symbol_to_csi(main_class_sym);
+	if (main_class == NULL) {
+		printf("Error: HelloWorld is not a CSI.\n");
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Found class '"); symbol_print_fqn(prog, main_class_sym);
+	printf("'.\n");
+#endif
+
+	/*
+	 * Resolve function @c main within the class.
+	 */
+	fake_ident->sid = strtab_get_sid("main");
+	main_fun_sym = symbol_lookup_in_csi(prog, main_class, fake_ident);
+	main_fun = symbol_to_fun(main_fun_sym);
+	if (main_fun == NULL) {
+		printf("Error: HelloWorld.main is not a function.\n");
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Found function '"); symbol_print_fqn(prog, main_fun_sym);
+	printf("'.\n");
+#endif
+
+	list_init(&main_args);
+	run_fun(run, main_fun, &main_args);
+}
+
+/** Run member function */
+void run_fun(run_t *run, stree_fun_t *fun, list_t *args)
+{
+	stree_symbol_t *fun_sym;
+	run_fun_ar_t *fun_ar;
+	run_block_ar_t *block_ar;
+	list_node_t *rarg_n, *farg_n;
+	list_node_t *node;
+	rdata_item_t *rarg;
+	stree_fun_arg_t *farg;
+	rdata_var_t *var;
+
+	fun_sym = fun_to_symbol(fun);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Start executing function '");
+	symbol_print_fqn(run->program, fun_sym);
+	printf("'.\n");
+#endif
+
+	/* Create function activation record. */
+	fun_ar = run_fun_ar_new();
+	fun_ar->fun_sym = fun_sym;
+	list_init(&fun_ar->block_ar);
+
+	/* Add function AR to the stack. */
+	list_append(&run->thread_ar->fun_ar, fun_ar);
+
+	/* Create special block activation record to hold function arguments. */
+	block_ar = run_block_ar_new();
+	intmap_init(&block_ar->vars);
+	list_append(&fun_ar->block_ar, block_ar);
+
+	/* Declare local variables to hold argument values. */
+	rarg_n = list_first(args);
+	farg_n = list_first(&fun->args);
+
+	while (farg_n != NULL) {
+		if (rarg_n == NULL) {
+			printf("Error: Too few arguments to function '");
+			symbol_print_fqn(run->program, fun_sym);
+			printf("'.\n");
+			exit(1);
+		}
+
+		rarg = list_node_data(rarg_n, rdata_item_t *);
+		farg = list_node_data(farg_n, stree_fun_arg_t *);
+
+		assert(rarg->ic == ic_value);
+
+		/* Construct a variable from the argument value. */
+		run_value_item_to_var(rarg, &var);
+
+		/* Declare variable using name of formal argument. */
+		intmap_set(&block_ar->vars, farg->name->sid, var);
+
+		rarg_n = list_next(args, rarg_n);
+		farg_n = list_next(&fun->args, farg_n);
+	}
+
+	/* Check for excess real parameters. */
+	if (rarg_n != NULL) {
+		printf("Error: Too many arguments to function '");
+		symbol_print_fqn(run->program, fun_sym);
+		printf("'.\n");
+		exit(1);
+	}
+
+	/* Run main function block. */
+	if (fun->body != NULL) {
+		run_block(run, fun->body);
+	} else {
+		builtin_run_fun(run, fun_sym);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Done executing function '");
+	symbol_print_fqn(run->program, fun_sym);
+	printf("'.\n");
+
+	run_print_fun_bt(run);
+#endif
+
+	/* Remove function activation record from the stack. */
+	node = list_last(&run->thread_ar->fun_ar);
+	assert(list_node_data(node, run_fun_ar_t *) == fun_ar);
+	list_remove(&run->thread_ar->fun_ar, node);
+}
+
+/** Run code block */
+static void run_block(run_t *run, stree_block_t *block)
+{
+	run_fun_ar_t *fun_ar;
+	run_block_ar_t *block_ar;
+	list_node_t *node;
+	stree_stat_t *stat;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing one code block.\n");
+#endif
+
+	/* Create block activation record. */
+	block_ar = run_block_ar_new();
+	intmap_init(&block_ar->vars);
+
+	/* Add block activation record to the stack. */
+	fun_ar = run_get_current_fun_ar(run);
+	list_append(&fun_ar->block_ar, block_ar);
+
+	node = list_first(&block->stats);
+	while (node != NULL) {
+		stat = list_node_data(node, stree_stat_t *);
+		run_stat(run, stat);
+		node = list_next(&block->stats, node);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Done executing code block.\n");
+#endif
+
+	/* Remove block activation record from the stack. */
+	node = list_last(&fun_ar->block_ar);
+	assert(list_node_data(node, run_block_ar_t *) == block_ar);
+	list_remove(&fun_ar->block_ar, node);
+}
+
+/** Run statement. */
+static void run_stat(run_t *run, stree_stat_t *stat)
+{
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing one statement %p.\n", stat);
+#endif
+
+	switch (stat->sc) {
+	case st_exps:
+		run_exps(run, stat->u.exp_s);
+		break;
+	case st_vdecl:
+		run_vdecl(run, stat->u.vdecl_s);
+		break;
+	case st_if:
+		run_if(run, stat->u.if_s);
+		break;
+	case st_while:
+		run_while(run, stat->u.while_s);
+		break;
+	case st_for:
+	case st_raise:
+	case st_wef:
+		printf("Ignoring unimplemented statement type %d.\n", stat->sc);
+		break;
+	default:
+		assert(b_false);
+	}
+}
+
+/** Run expression statement. */
+static void run_exps(run_t *run, stree_exps_t *exps)
+{
+	rdata_item_t *rexpr;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing expression statement.\n");
+#endif
+	run_expr(run, exps->expr, &rexpr);
+
+	if (rexpr != NULL) {
+		printf("Warning: Expression value ignored.\n");
+	}
+}
+
+/** Run variable declaration statement. */
+static void run_vdecl(run_t *run, stree_vdecl_t *vdecl)
+{
+	run_block_ar_t *block_ar;
+	rdata_var_t *var, *old_var;
+	rdata_int_t *int_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing variable declaration statement.\n");
+#endif
+
+	/* XXX Need to support other variables than int. */
+
+	var = rdata_var_new(vc_int);
+	int_v = rdata_int_new();
+
+	var->u.int_v = int_v;
+	int_v->value = 0;
+
+	block_ar = run_get_current_block_ar(run);
+	old_var = (rdata_var_t *) intmap_get(&block_ar->vars, vdecl->name->sid);
+
+	if (old_var != NULL) {
+		printf("Error: Duplicate variable '%s'\n",
+		    strtab_get_str(vdecl->name->sid));
+		exit(1);
+	}
+
+	intmap_set(&block_ar->vars, vdecl->name->sid, var);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Declared variable '%s'\n", strtab_get_str(vdecl->name->sid));
+#endif
+}
+
+/** Run @c if statement. */
+static void run_if(run_t *run, stree_if_t *if_s)
+{
+	rdata_item_t *rcond;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing if statement.\n");
+#endif
+	run_expr(run, if_s->cond, &rcond);
+
+	if (run_item_boolean_value(run, rcond) == b_true) {
+#ifdef DEBUG_RUN_TRACE
+		printf("Taking true path.\n");
+#endif
+		run_block(run, if_s->if_block);
+	} else {
+#ifdef DEBUG_RUN_TRACE
+		printf("Taking false path.\n");
+#endif
+        	if (if_s->else_block != NULL)
+			run_block(run, if_s->else_block);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("If statement terminated.\n");
+#endif
+}
+
+/** Run @c while statement. */
+static void run_while(run_t *run, stree_while_t *while_s)
+{
+	rdata_item_t *rcond;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing while statement.\n");
+#endif
+	run_expr(run, while_s->cond, &rcond);
+
+	while (run_item_boolean_value(run, rcond) == b_true) {
+		run_block(run, while_s->body);
+		run_expr(run, while_s->cond, &rcond);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("While statement terminated.\n");
+#endif
+}
+
+/** Find a local variable in the currently active function. */
+rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name)
+{
+	run_fun_ar_t *fun_ar;
+	run_block_ar_t *block_ar;
+	rdata_var_t *var;
+	list_node_t *node;
+
+	fun_ar = run_get_current_fun_ar(run);
+	node = list_last(&fun_ar->block_ar);
+
+	/* Walk through all block activation records. */
+	while (node != NULL) {
+		block_ar = list_node_data(node, run_block_ar_t *);
+		var = intmap_get(&block_ar->vars, name);
+		if (var != NULL)
+			return var;
+
+		node = list_prev(&fun_ar->block_ar, node);
+	}
+
+	/* No match */
+	return NULL;
+}
+
+/** Get current function activation record. */
+run_fun_ar_t *run_get_current_fun_ar(run_t *run)
+{
+	list_node_t *node;
+
+	node = list_last(&run->thread_ar->fun_ar);
+	return list_node_data(node, run_fun_ar_t *);
+}
+
+/** Get current block activation record. */
+run_block_ar_t *run_get_current_block_ar(run_t *run)
+{
+	run_fun_ar_t *fun_ar;
+	list_node_t *node;
+
+	fun_ar = run_get_current_fun_ar(run);
+
+	node = list_last(&fun_ar->block_ar);
+	return list_node_data(node, run_block_ar_t *);
+}
+
+/** Construct variable from a value item.
+ *
+ * XXX This should be in fact implemented using existing code as:
+ *
+ * (1) Create a variable of the desired type.
+ * (2) Initialize the variable with the provided value.
+ */
+static void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
+{
+	rdata_int_t *int_v;
+	rdata_string_t *string_v;
+	rdata_var_t *in_var;
+
+	assert(item->ic == ic_value);
+	in_var = item->u.value->var;
+
+	switch (in_var->vc) {
+	case vc_int:
+		*var = rdata_var_new(vc_int);
+		int_v = rdata_int_new();
+
+		(*var)->u.int_v = int_v;
+		int_v->value = item->u.value->var->u.int_v->value;
+		break;
+	case vc_string:
+		*var = rdata_var_new(vc_string);
+		string_v = rdata_string_new();
+
+		(*var)->u.string_v = string_v;
+		string_v->value = item->u.value->var->u.string_v->value;
+		break;
+	default:
+		printf("Error: Unimplemented argument type.\n");
+		exit(1);
+
+	}
+}
+
+/** Print function activation backtrace. */
+void run_print_fun_bt(run_t *run)
+{
+	list_node_t *node;
+	run_fun_ar_t *fun_ar;
+
+	printf("Backtrace:\n");
+	node = list_last(&run->thread_ar->fun_ar);
+	while (node != NULL) {
+		printf(" * ");
+		fun_ar = list_node_data(node, run_fun_ar_t *);
+		symbol_print_fqn(run->program, fun_ar->fun_sym);
+		printf("\n");
+
+		node = list_prev(&run->thread_ar->fun_ar, node);
+	}
+}
+
+run_thread_ar_t *run_thread_ar_new(void)
+{
+	run_thread_ar_t *thread_ar;
+
+	thread_ar = calloc(1, sizeof(run_thread_ar_t));
+	if (thread_ar == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return thread_ar;
+}
+
+run_fun_ar_t *run_fun_ar_new(void)
+{
+	run_fun_ar_t *fun_ar;
+
+	fun_ar = calloc(1, sizeof(run_fun_ar_t));
+	if (fun_ar == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return fun_ar;
+}
+
+run_block_ar_t *run_block_ar_new(void)
+{
+	run_block_ar_t *block_ar;
+
+	block_ar = calloc(1, sizeof(run_block_ar_t));
+	if (block_ar == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return block_ar;
+}
Index: uspace/app/sbi/src/run.h
===================================================================
--- uspace/app/sbi/src/run.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RUN_H_
+#define RUN_H_
+
+#include "mytypes.h"
+
+void run_init(run_t *run);
+void run_program(run_t *run, stree_program_t *prog);
+void run_fun(run_t *run, stree_fun_t *fun, list_t *args);
+
+void run_print_fun_bt(run_t *run);
+
+rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name);
+run_fun_ar_t *run_get_current_fun_ar(run_t *run);
+run_block_ar_t *run_get_current_block_ar(run_t *run);
+
+run_thread_ar_t *run_thread_ar_new(void);
+run_fun_ar_t *run_fun_ar_new(void);
+run_block_ar_t *run_block_ar_new(void);
+
+#endif
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run_expr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Runner (executes the code). */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "debug.h"
+#include "list.h"
+#include "mytypes.h"
+#include "rdata.h"
+#include "run.h"
+#include "symbol.h"
+#include "strtab.h"
+
+#include "run_expr.h"
+
+static void run_nameref(run_t *run, stree_nameref_t *nameref,
+    rdata_item_t **res);
+static void run_literal(run_t *run, stree_literal_t *literal,
+    rdata_item_t **res);
+static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
+    rdata_item_t **res);
+static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
+    rdata_item_t **res);
+static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
+static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
+static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
+static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
+static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
+
+static void run_address_read(run_t *run, rdata_address_t *address,
+    rdata_item_t **ritem);
+static void run_address_write(run_t *run, rdata_address_t *address,
+    rdata_value_t *value);
+
+/** Evaluate expression. */
+void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
+{
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing expression.\n");
+#endif
+
+	switch (expr->ec) {
+	case ec_nameref:
+		run_nameref(run, expr->u.nameref, res);
+		break;
+	case ec_literal:
+		run_literal(run, expr->u.literal, res);
+		break;
+	case ec_binop:
+		run_binop(run, expr->u.binop, res);
+		break;
+	case ec_unop:
+		run_unop(run, expr->u.unop, res);
+		break;
+	case ec_access:
+		run_access(run, expr->u.access, res);
+		break;
+	case ec_call:
+		run_call(run, expr->u.call, res);
+		break;
+	case ec_assign:
+		run_assign(run, expr->u.assign, res);
+		break;
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Expression result: ");
+	rdata_item_print(*res);
+	printf(".\n");
+#endif
+}
+
+/** Evaluate name reference expression. */
+static void run_nameref(run_t *run, stree_nameref_t *nameref,
+    rdata_item_t **res)
+{
+	stree_symbol_t *sym;
+	rdata_item_t *item;
+	rdata_address_t *address;
+	rdata_value_t *val;
+	rdata_var_t *var;
+	rdata_deleg_t *deleg_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run nameref.\n");
+#endif
+
+	/*
+	 * Look for a local variable.
+	 */
+	var = run_local_vars_lookup(run, nameref->name->sid);
+	if (var != NULL) {
+		/* Found a local variable. */
+		item = rdata_item_new(ic_address);
+		address = rdata_address_new();
+
+		item->u.address = address;
+		address->vref = var;
+
+		*res = item;
+#ifdef DEBUG_RUN_TRACE
+		printf("Found local variable.\n");
+#endif
+		return;
+	}
+
+	/*
+	 * Look for a class-wide or global symbol.
+	 */
+
+	/* XXX Start lookup in currently active CSI. */
+	sym = symbol_lookup_in_csi(run->program, NULL, nameref->name);
+
+	switch (sym->sc) {
+	case sc_csi:
+#ifdef DEBUG_RUN_TRACE
+		printf("Referencing class.\n");
+#endif
+		item = rdata_item_new(ic_value);
+		val = rdata_value_new();
+		var = rdata_var_new(vc_deleg);
+		deleg_v = rdata_deleg_new();
+
+		item->u.value = val;
+		val->var = var;
+		var->u.deleg_v = deleg_v;
+
+		deleg_v->obj = NULL;
+		deleg_v->sym = sym;
+		*res = item;
+		break;
+	default:
+		printf("Referencing symbol class %d unimplemented.\n", sym->sc);
+		*res = NULL;
+		break;
+	}
+}
+
+/** Evaluate literal. */
+static void run_literal(run_t *run, stree_literal_t *literal,
+    rdata_item_t **res)
+{
+#ifdef DEBUG_RUN_TRACE
+	printf("Run literal.\n");
+#endif
+
+	switch (literal->ltc) {
+	case ltc_int:
+		run_lit_int(run, &literal->u.lit_int, res);
+		break;
+	case ltc_string:
+		run_lit_string(run, &literal->u.lit_string, res);
+		break;
+	default:
+		assert(b_false);
+	}
+}
+
+/** Evaluate integer literal. */
+static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
+    rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_int_t *int_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run integer literal.\n");
+#endif
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_int);
+	int_v = rdata_int_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.int_v = int_v;
+	int_v->value = lit_int->value;
+
+	*res = item;
+}
+
+/** Evaluate string literal. */
+static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
+    rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_string_t *string_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run integer literal.\n");
+#endif
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_string);
+	string_v = rdata_string_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.string_v = string_v;
+	string_v->value = lit_string->value;
+
+	*res = item;
+}
+
+
+/** Evaluate binary operation. */
+static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
+{
+	rdata_item_t *rarg1_i, *rarg2_i;
+	rdata_item_t *rarg1_vi, *rarg2_vi;
+	rdata_value_t *v1, *v2;
+	int i1, i2;
+
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_int_t *int_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run binary operation.\n");
+#endif
+	run_expr(run, binop->arg1, &rarg1_i);
+	run_expr(run, binop->arg2, &rarg2_i);
+
+	switch (binop->bc) {
+	case bo_plus:
+	case bo_equal:
+	case bo_notequal:
+	case bo_lt:
+	case bo_gt:
+	case bo_lt_equal:
+	case bo_gt_equal:
+		/* These are implemented so far. */
+		break;
+	default:
+		printf("Unimplemented: Binary operation type %d.\n",
+		    binop->bc);
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Check binop argument results.\n");
+#endif
+
+	run_cvt_value_item(run, rarg1_i, &rarg1_vi);
+	run_cvt_value_item(run, rarg2_i, &rarg2_vi);
+
+	v1 = rarg1_vi->u.value;
+	v2 = rarg2_vi->u.value;
+
+	if (v1->var->vc != vc_int || v2->var->vc != vc_int) {
+		printf("Unimplemented: Binary operation arguments are not "
+		    "integer values.\n");
+		exit(1);
+	}
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_int);
+	int_v = rdata_int_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.int_v = int_v;
+
+	i1 = v1->var->u.int_v->value;
+	i2 = v2->var->u.int_v->value;
+
+	switch (binop->bc) {
+	case bo_plus:
+		int_v->value = i1 + i2;
+		break;
+
+	/* XXX We should have a real boolean type. */
+	case bo_equal:
+		int_v->value = (i1 == i2) ? 1 : 0;
+		break;
+	case bo_notequal:
+		int_v->value = (i1 != i2) ? 1 : 0;
+		break;
+	case bo_lt:
+		int_v->value = (i1 < i2) ? 1 : 0;
+		break;
+	case bo_gt:
+		int_v->value = (i1 > i2) ? 1 : 0;
+		break;
+	case bo_lt_equal:
+		int_v->value = (i1 <= i2) ? 1 : 0;
+		break;
+	case bo_gt_equal:
+		int_v->value = (i1 >= i2) ? 1 : 0;
+		break;
+	default:
+		assert(b_false);
+	}
+
+	*res = item;
+}
+
+/** Evaluate unary operation. */
+static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
+{
+	rdata_item_t *rarg;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run unary operation.\n");
+#endif
+	run_expr(run, unop->arg, &rarg);
+	*res = NULL;
+}
+
+/** Evaluate member acccess. */
+static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
+{
+	rdata_item_t *rarg;
+	rdata_deleg_t *deleg_v;
+	stree_symbol_t *member;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run access operation.\n");
+#endif
+	run_expr(run, access->arg, &rarg);
+
+	if (rarg->ic == ic_value && rarg->u.value->var->vc == vc_deleg) {
+#ifdef DEBUG_RUN_TRACE
+		printf("Accessing delegate.\n");
+#endif
+		deleg_v = rarg->u.value->var->u.deleg_v;
+		if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
+			printf("Error: Using '.' with symbol of wrong "
+			    "type (%d).\n", deleg_v->sym->sc);
+			exit(1);
+		}
+
+		member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
+		    access->member_name);
+
+		if (member == NULL) {
+			printf("Error: No such member.\n");
+			exit(1);
+		}
+
+#ifdef DEBUG_RUN_TRACE
+		printf("Found member '%s'.\n",
+		    strtab_get_str(access->member_name->sid));
+#endif
+
+		/* Reuse existing item, value, var, deleg. */
+		deleg_v->sym = member;
+
+		*res = rarg;
+		return;
+	}
+
+	*res = NULL;
+}
+
+/** Call a function. */
+static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
+{
+	rdata_item_t *rfun;
+	rdata_deleg_t *deleg_v;
+	list_t arg_vals;
+	list_node_t *node;
+	stree_expr_t *arg;
+	rdata_item_t *rarg_i, *rarg_vi;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run call operation.\n");
+#endif
+	run_expr(run, call->fun, &rfun);
+
+	if (rfun->ic != ic_value || rfun->u.value->var->vc != vc_deleg) {
+		printf("Unimplemented: Call expression of this type.\n");
+		*res = NULL;
+		return;
+	}
+
+	deleg_v = rfun->u.value->var->u.deleg_v;
+
+	if (deleg_v->sym->sc != sc_fun) {
+		printf("Error: Called symbol is not a function.\n");
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Call function '");
+	symbol_print_fqn(run->program, deleg_v->sym);
+	printf("'\n");
+#endif
+
+	/* Evaluate function arguments. */
+	list_init(&arg_vals);
+	node = list_first(&call->args);
+
+	while (node != NULL) {
+		arg = list_node_data(node, stree_expr_t *);
+		run_expr(run, arg, &rarg_i);
+		run_cvt_value_item(run, rarg_i, &rarg_vi);
+
+		list_append(&arg_vals, rarg_vi);
+		node = list_next(&call->args, node);
+	}
+
+	run_fun(run, deleg_v->sym->u.fun, &arg_vals);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Returned from function call.\n");
+#endif
+	*res = NULL;
+}
+
+/** Execute assignment. */
+static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
+{
+	rdata_item_t *rdest_i, *rsrc_i;
+	rdata_item_t *rsrc_vi;
+	rdata_value_t *src_val;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run assign operation.\n");
+#endif
+	run_expr(run, assign->dest, &rdest_i);
+	run_expr(run, assign->src, &rsrc_i);
+
+	run_cvt_value_item(run, rsrc_i, &rsrc_vi);
+	src_val = rsrc_vi->u.value;
+
+	if (rdest_i->ic != ic_address) {
+		printf("Error: Address expression required on left side of "
+		    "assignment operator.\n");
+		exit(1);
+	}
+
+	run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
+
+	*res = NULL;
+}
+
+/** Return boolean value of an item.
+ *
+ * Tries to interpret @a item as a boolean value. If it is not a boolean
+ * value, this generates an error.
+ *
+ * XXX Currently int supplants the role of a true boolean type.
+ */
+bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
+{
+	rdata_item_t *vitem;
+	rdata_var_t *var;
+
+	run_cvt_value_item(run, item, &vitem);
+
+	assert(vitem->ic == ic_value);
+	var = vitem->u.value->var;
+
+	if (var->vc != vc_int) {
+		printf("Error: Boolean (int) expression expected.\n");
+		exit(1);
+	}
+
+	return (var->u.int_v->value != 0);
+}
+
+/** Convert item to value item.
+ *
+ * If @a item is a value, we just return a copy. If @a item is an address,
+ * we read from the address.
+ */
+void run_cvt_value_item(run_t *run, rdata_item_t *item,
+    rdata_item_t **ritem)
+{
+	rdata_value_t *value;
+
+	/* Address item. Perform read operation. */
+	if (item->ic == ic_address) {
+		run_address_read(run, item->u.address, ritem);
+		return;
+	}
+
+	/* It already is a value, we can share the @c var. */
+	value = rdata_value_new();
+	value->var = item->u.value->var;
+	*ritem = rdata_item_new(ic_value);
+	(*ritem)->u.value = value;
+}
+
+/** Read data from an address.
+ *
+ * Return value stored in a variable at the specified address.
+ */
+static void run_address_read(run_t *run, rdata_address_t *address,
+    rdata_item_t **ritem)
+{
+	rdata_value_t *value;
+	rdata_var_t *rvar;
+	(void) run;
+
+	/* Perform a shallow copy of @c var. */
+	rdata_var_copy(address->vref, &rvar);
+
+	value = rdata_value_new();
+	value->var = rvar;
+	*ritem = rdata_item_new(ic_value);
+	(*ritem)->u.value = value;
+}
+
+/** Write data to an address.
+ *
+ * Store @a value to the variable at @a address.
+ */
+static void run_address_write(run_t *run, rdata_address_t *address,
+    rdata_value_t *value)
+{
+	rdata_var_t *nvar;
+	rdata_var_t *orig_var;
+
+	/* Perform a shallow copy of @c value->var. */
+	rdata_var_copy(value->var, &nvar);
+	orig_var = address->vref;
+
+	/* XXX do this in a prettier way. */
+
+	orig_var->vc = nvar->vc;
+	switch (nvar->vc) {
+	case vc_int: orig_var->u.int_v = nvar->u.int_v; break;
+	case vc_ref: orig_var->u.ref_v = nvar->u.ref_v; break;
+	case vc_deleg: orig_var->u.deleg_v = nvar->u.deleg_v; break;
+	case vc_object: orig_var->u.object_v = nvar->u.object_v; break;
+	default: assert(b_false);
+	}
+
+	/* XXX We should free some stuff around here. */
+}
Index: uspace/app/sbi/src/run_expr.h
===================================================================
--- uspace/app/sbi/src/run_expr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run_expr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RUN_EXPR_H_
+#define RUN_EXPR_H_
+
+#include "mytypes.h"
+
+void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res);
+
+void run_cvt_value_item(run_t *run, rdata_item_t *item,
+    rdata_item_t **ritem);
+bool_t run_item_boolean_value(run_t *run, rdata_item_t *item);
+
+
+#endif
Index: uspace/app/sbi/src/run_t.h
===================================================================
--- uspace/app/sbi/src/run_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RUN_T_H_
+#define RUN_T_H_
+
+#include "list_t.h"
+
+/** Block activation record
+ *
+ * One block AR is created for each block that we enter. A variable declaration
+ * statement inserts the variable here. Upon exiting the block we pop from the
+ * stack, thus all the variables declared in that block are forgotten.
+ */
+typedef struct run_block_ar {
+	/** Variables in this block */
+	intmap_t vars; /* of rdata_var_t */
+} run_block_ar_t;
+
+/** Function activation record
+ *
+ * One is created whenever a function is invoked.
+ */
+typedef struct run_fun_ar {
+	/** Definition of function being invoked */
+	struct stree_symbol *fun_sym;
+
+	/** Block activation records */
+	list_t block_ar; /* of run_block_ar_t */
+} run_fun_ar_t;
+
+/** Thread activation record
+ *
+ * We can walk the list of function ARs to get a function call backtrace.
+ */
+typedef struct run_thread_ar {
+	/** Function activation records. */
+	list_t fun_ar; /* of run_fun_ar_t */
+} run_thread_ar_t;
+
+/** Runner state object */
+typedef struct run {
+	/** Code of the program being executed */
+	struct stree_program *program;
+
+	/** Thread-private state */
+	run_thread_ar_t *thread_ar;
+} run_t;
+
+#endif
Index: uspace/app/sbi/src/stree.c
===================================================================
--- uspace/app/sbi/src/stree.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/stree.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Stree (syntax tree) intermediate representation. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "list.h"
+#include "mytypes.h"
+
+#include "stree.h"
+
+stree_module_t *stree_module_new(void)
+{
+	stree_module_t *module;
+
+	module = calloc(1, sizeof(stree_module_t));
+	if (module == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	list_init(&module->members);
+	return module;
+}
+
+stree_modm_t *stree_modm_new(modm_class_t mc)
+{
+	stree_modm_t *modm;
+
+	modm = calloc(1, sizeof(stree_modm_t));
+	if (modm == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	modm->mc = mc;
+	return modm;
+}
+
+stree_csi_t *stree_csi_new(csi_class_t cc)
+{
+	stree_csi_t *csi;
+
+	csi = calloc(1, sizeof(stree_csi_t));
+	if (csi == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	csi->cc = cc;
+	csi->ancr_state = ws_unvisited;
+	csi->name = NULL;
+	csi->base_csi_ref = NULL;
+	list_init(&csi->members);
+	return csi;
+}
+
+stree_csimbr_t *stree_csimbr_new(csimbr_class_t cc)
+{
+	stree_csimbr_t *csimbr;
+
+	csimbr = calloc(1, sizeof(stree_csimbr_t));
+	if (csimbr == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	csimbr->cc = cc;
+	return csimbr;
+}
+
+stree_fun_t *stree_fun_new(void)
+{
+	stree_fun_t *fun;
+
+	fun = calloc(1, sizeof(stree_fun_t));
+	if (fun == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return fun;
+}
+
+stree_var_t *stree_var_new(void)
+{
+	stree_var_t *var;
+
+	var = calloc(1, sizeof(stree_var_t));
+	if (var == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return var;
+}
+
+stree_prop_t *stree_prop_new(void)
+{
+	stree_prop_t *prop;
+
+	prop = calloc(1, sizeof(stree_prop_t));
+	if (prop == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return prop;
+}
+
+stree_fun_arg_t *stree_fun_arg_new(void)
+{
+	stree_fun_arg_t *fun_arg;
+
+	fun_arg = calloc(1, sizeof(stree_fun_arg_t));
+	if (fun_arg == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return fun_arg;
+}
+
+stree_stat_t *stree_stat_new(stat_class_t sc)
+{
+	stree_stat_t *stat;
+
+	stat = calloc(1, sizeof(stree_stat_t));
+	if (stat == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	stat->sc = sc;
+	return stat;
+}
+
+stree_vdecl_t *stree_vdecl_new(void)
+{
+	stree_vdecl_t *vdecl_s;
+
+	vdecl_s = calloc(1, sizeof(stree_vdecl_t));
+	if (vdecl_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return vdecl_s;
+}
+
+stree_if_t *stree_if_new(void)
+{
+	stree_if_t *if_s;
+
+	if_s = calloc(1, sizeof(stree_if_t));
+	if (if_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return if_s;
+}
+
+stree_while_t *stree_while_new(void)
+{
+	stree_while_t *while_s;
+
+	while_s = calloc(1, sizeof(stree_while_t));
+	if (while_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return while_s;
+}
+
+stree_for_t *stree_for_new(void)
+{
+	stree_for_t *for_s;
+
+	for_s = calloc(1, sizeof(stree_for_t));
+	if (for_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return for_s;
+}
+
+stree_raise_t *stree_raise_new(void)
+{
+	stree_raise_t *raise_s;
+
+	raise_s = calloc(1, sizeof(stree_raise_t));
+	if (raise_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return raise_s;
+}
+
+stree_wef_t *stree_wef_new(void)
+{
+	stree_wef_t *wef_s;
+
+	wef_s = calloc(1, sizeof(stree_wef_t));
+	if (wef_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return wef_s;
+}
+
+stree_exps_t *stree_exps_new(void)
+{
+	stree_exps_t *exp_s;
+
+	exp_s = calloc(1, sizeof(stree_exps_t));
+	if (exp_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return exp_s;
+}
+
+stree_block_t *stree_block_new(void)
+{
+	stree_block_t *block;
+
+	block = calloc(1, sizeof(stree_block_t));
+	if (block == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return block;
+}
+
+stree_expr_t *stree_expr_new(expr_class_t ec)
+{
+	stree_expr_t *expr;
+
+	expr = calloc(1, sizeof(stree_expr_t));
+	if (expr == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	expr->ec = ec;
+	return expr;
+}
+
+stree_assign_t *stree_assign_new(assign_class_t ac)
+{
+	stree_assign_t *assign;
+
+	assign = calloc(1, sizeof(stree_assign_t));
+	if (assign == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	assign->ac = ac;
+	return assign;
+}
+
+stree_binop_t *stree_binop_new(binop_class_t bc)
+{
+	stree_binop_t *binop;
+
+	binop = calloc(1, sizeof(stree_binop_t));
+	if (binop == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	binop->bc = bc;
+	return binop;
+}
+
+stree_access_t *stree_access_new(void)
+{
+	stree_access_t *access;
+
+	access = calloc(1, sizeof(stree_access_t));
+	if (access == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return access;
+}
+
+stree_call_t *stree_call_new(void)
+{
+	stree_call_t *call;
+
+	call = calloc(1, sizeof(stree_call_t));
+	if (call == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return call;
+}
+
+stree_nameref_t *stree_nameref_new(void)
+{
+	stree_nameref_t *nameref;
+
+	nameref = calloc(1, sizeof(stree_nameref_t));
+	if (nameref == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return nameref;
+}
+
+stree_ident_t *stree_ident_new(void)
+{
+	stree_ident_t *ident;
+
+	ident = calloc(1, sizeof(stree_ident_t));
+	if (ident == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return ident;
+}
+
+stree_literal_t *stree_literal_new(literal_class_t ltc)
+{
+	stree_literal_t *literal;
+
+	literal = calloc(1, sizeof(stree_literal_t));
+	if (literal == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	literal->ltc = ltc;
+	return literal;
+}
+
+stree_texpr_t *stree_texpr_new(texpr_class_t tc)
+{
+	stree_texpr_t *texpr;
+
+	texpr = calloc(1, sizeof(stree_texpr_t));
+	if (texpr == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	texpr->tc = tc;
+	return texpr;
+}
+
+stree_tapply_t *stree_tapply_new(void)
+{
+	stree_tapply_t *tapply;
+
+	tapply = calloc(1, sizeof(stree_tapply_t));
+	if (tapply == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return tapply;
+}
+
+stree_taccess_t *stree_taccess_new(void)
+{
+	stree_taccess_t *taccess;
+
+	taccess = calloc(1, sizeof(stree_taccess_t));
+	if (taccess == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return taccess;
+}
+
+stree_tnameref_t *stree_tnameref_new(void)
+{
+	stree_tnameref_t *tnameref;
+
+	tnameref = calloc(1, sizeof(stree_tnameref_t));
+	if (tnameref == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return tnameref;
+}
+
+stree_symbol_t *stree_symbol_new(symbol_class_t sc)
+{
+	stree_symbol_t *symbol;
+
+	symbol = calloc(1, sizeof(stree_symbol_t));
+	if (symbol == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	symbol->sc = sc;
+	return symbol;
+}
+
+stree_program_t *stree_program_new(void)
+{
+	stree_program_t *program;
+
+	program = calloc(1, sizeof(stree_program_t));
+	if (program == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return program;
+}
Index: uspace/app/sbi/src/stree.h
===================================================================
--- uspace/app/sbi/src/stree.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/stree.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STREE_H_
+#define STREE_H_
+
+#include "mytypes.h"
+
+stree_module_t *stree_module_new(void);
+stree_modm_t *stree_modm_new(modm_class_t mc);
+stree_csi_t *stree_csi_new(csi_class_t cc);
+stree_csimbr_t *stree_csimbr_new(csimbr_class_t cc);
+stree_fun_t *stree_fun_new(void);
+stree_var_t *stree_var_new(void);
+stree_prop_t *stree_prop_new(void);
+
+stree_fun_arg_t *stree_fun_arg_new(void);
+
+stree_stat_t *stree_stat_new(stat_class_t sc);
+stree_vdecl_t *stree_vdecl_new(void);
+stree_if_t *stree_if_new(void);
+stree_while_t *stree_while_new(void);
+stree_for_t *stree_for_new(void);
+stree_raise_t *stree_raise_new(void);
+stree_wef_t *stree_wef_new(void);
+stree_exps_t *stree_exps_new(void);
+stree_block_t *stree_block_new(void);
+
+stree_expr_t *stree_expr_new(expr_class_t ec);
+stree_assign_t *stree_assign_new(assign_class_t ac);
+stree_binop_t *stree_binop_new(binop_class_t bc);
+stree_access_t *stree_access_new(void);
+stree_call_t *stree_call_new(void);
+stree_nameref_t *stree_nameref_new(void);
+
+stree_ident_t *stree_ident_new(void);
+stree_literal_t *stree_literal_new(literal_class_t ltc);
+
+stree_texpr_t *stree_texpr_new(texpr_class_t tc);
+stree_tapply_t *stree_tapply_new(void);
+stree_taccess_t *stree_taccess_new(void);
+stree_tnameref_t *stree_tnameref_new(void);
+
+stree_symbol_t *stree_symbol_new(symbol_class_t sc);
+stree_program_t *stree_program_new(void);
+
+#endif
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/stree_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STREE_T_H_
+#define STREE_T_H_
+
+#include "list_t.h"
+
+/*
+ * Arithmetic expressions
+ */
+
+struct stree_expr;
+
+/** Identifier */
+typedef struct {
+	int sid;
+} stree_ident_t;
+
+/** Name reference */
+typedef struct {
+	stree_ident_t *name;
+} stree_nameref_t;
+
+typedef struct {
+	int value;
+} stree_lit_int_t;
+
+typedef struct {
+	char *value;
+} stree_lit_string_t;
+
+typedef enum {
+	ltc_int,
+	ltc_string
+} literal_class_t;
+
+/** Literal */
+typedef struct {
+	literal_class_t ltc;
+	union {
+		stree_lit_int_t lit_int;
+		stree_lit_string_t lit_string;
+	} u;
+} stree_literal_t;
+
+/** Binary operation class */
+typedef enum {
+	bo_period,
+	bo_slash,
+	bo_sbr,
+	bo_equal,
+	bo_notequal,
+	bo_lt,
+	bo_gt,
+	bo_lt_equal,
+	bo_gt_equal,
+	bo_plus
+} binop_class_t;
+
+/** Unary operation class */
+typedef enum {
+	uo_plus
+} unop_class_t;
+
+/** Binary operation */
+typedef struct {
+	/** Binary operation class */
+	binop_class_t bc;
+
+	/** Arguments */
+	struct stree_expr *arg1, *arg2;
+} stree_binop_t;
+
+/** Unary operation */
+typedef struct {
+	/** Operation class */
+	unop_class_t oc;
+
+	/** Argument */
+	struct stree_expr *arg;
+} stree_unop_t;
+
+/** Member access operation */
+typedef struct {
+	/** Argument */
+	struct stree_expr *arg;
+	/** Name of member being accessed. */
+	stree_ident_t *member_name;
+} stree_access_t;
+
+/** Function call operation */
+typedef struct {
+	/** Function */
+	struct stree_expr *fun;
+
+	/** Arguments */
+	list_t args; /* of stree_expr_t */
+} stree_call_t;
+
+typedef enum {
+	ac_set,
+	ac_increase
+} assign_class_t;
+
+/** Assignment */
+typedef struct {
+	assign_class_t ac;
+	struct stree_expr *dest, *src;
+} stree_assign_t;
+
+/** Arithmetic expression class */
+typedef enum {
+	ec_nameref,
+	ec_literal,
+	ec_binop,
+	ec_unop,
+	ec_access,
+	ec_call,
+	ec_assign
+} expr_class_t;
+
+/** Arithmetic expression */
+typedef struct stree_expr {
+	expr_class_t ec;
+
+	union {
+		stree_nameref_t *nameref;
+		stree_literal_t *literal;
+		stree_binop_t *binop;
+		stree_unop_t *unop;
+		stree_access_t *access;
+		stree_call_t *call;
+		stree_assign_t *assign;
+	} u;
+} stree_expr_t;
+
+/*
+ * Type expressions
+ */
+
+struct stree_texpr;
+
+/** Type name reference */
+typedef struct {
+	stree_ident_t *name;
+} stree_tnameref_t;
+
+/** Type member access operation */
+typedef struct {
+	/** Argument */
+	struct stree_texpr *arg;
+	/** Name of member being accessed. */
+	stree_ident_t *member_name;
+} stree_taccess_t;
+
+/** Type application operation */
+typedef struct {
+	/** Arguments */
+	struct stree_texpr *gtype, *targ;
+} stree_tapply_t;
+
+/** Type expression class */
+typedef enum {
+	tc_tnameref,
+	tc_taccess,
+	tc_tapply
+} texpr_class_t;
+
+/** Arithmetic expression */
+typedef struct stree_texpr {
+	texpr_class_t tc;
+
+	union {
+		stree_tnameref_t *tnameref;
+		stree_taccess_t *taccess;
+		stree_tapply_t *tapply;
+	} u;
+} stree_texpr_t;
+
+/*
+ * Statements, class members and module members.
+ */
+
+/** Statement block */
+typedef struct {
+	/** List of statements in the block */
+	list_t stats; /* of stree_stat_t */
+} stree_block_t;
+
+/** Variable declaration */
+typedef struct {
+	stree_ident_t *name;
+	stree_texpr_t *type;
+} stree_vdecl_t;
+
+/** If statement */
+typedef struct {
+	stree_expr_t *cond;
+	stree_block_t *if_block;
+	stree_block_t *else_block;
+} stree_if_t;
+
+/** While statement */
+typedef struct {
+	stree_expr_t *cond;
+	stree_block_t *body;
+} stree_while_t;
+
+/** For statement */
+typedef struct {
+	stree_block_t *body;
+} stree_for_t;
+
+/** Raise statement */
+typedef struct {
+} stree_raise_t;
+
+/** Expression statement */
+typedef struct {
+	stree_expr_t *expr;
+} stree_exps_t;
+
+/** With-try-except-finally statement (WEF) */
+typedef struct {
+	stree_block_t *with_block;
+	list_t except_blocks; /* of stree_block_t */
+	stree_block_t *finally_block;
+} stree_wef_t;
+
+/** Statement class */
+typedef enum {
+	st_vdecl,
+	st_if,
+	st_while,
+	st_for,
+	st_raise,
+	st_exps,
+	st_wef
+} stat_class_t;
+
+/** Statement */
+typedef struct {
+	stat_class_t sc;
+
+	union {
+		stree_vdecl_t *vdecl_s;
+		stree_if_t *if_s;
+		stree_while_t *while_s;
+		stree_for_t *for_s;
+		stree_raise_t *raise_s;
+		stree_exps_t *exp_s;
+		stree_wef_t *wef_s;
+	} u;
+} stree_stat_t;
+
+/** Formal function parameter */
+typedef struct {
+	/* Argument name */
+	stree_ident_t *name;
+
+	/* Argument type */
+	stree_texpr_t *type;
+} stree_fun_arg_t;
+
+/** Member function declaration */
+typedef struct {
+	/** Function name */
+	stree_ident_t *name;
+
+	/** Symbol */
+	struct stree_symbol *symbol;
+
+	/** Formal parameters */
+	list_t args; /* of stree_fun_arg_t */
+
+	/** Return type */
+	stree_texpr_t *rtype;
+
+	/** Function body */
+	stree_block_t *body;
+} stree_fun_t;
+
+/** Member variable declaration */
+typedef struct {
+	stree_ident_t *name;
+	struct stree_symbol *symbol;
+	stree_texpr_t *type;
+} stree_var_t;
+
+/** Member property declaration */
+typedef struct {
+	stree_ident_t *name;
+	struct stree_symbol *symbol;
+	stree_texpr_t *type;
+} stree_prop_t;
+
+typedef enum {
+	csimbr_csi,
+	csimbr_fun,
+	csimbr_var,
+	csimbr_prop
+} csimbr_class_t;
+
+/** Class, struct or interface member */
+typedef struct {
+	csimbr_class_t cc;
+
+	union {
+		struct stree_csi *csi;
+		stree_fun_t *fun;
+		stree_var_t *var;
+		stree_prop_t *prop;
+	} u;
+} stree_csimbr_t;
+
+typedef enum {
+	csi_class,
+	csi_struct,
+	csi_interface
+} csi_class_t;
+
+/** Class, struct or interface declaration */
+typedef struct stree_csi {
+	/** Which of class, struct or interface */
+	csi_class_t cc;
+
+	/** Name of this CSI */
+	stree_ident_t *name;
+
+	/** Symbol for this CSI */
+	struct stree_symbol *symbol;
+
+	/** Type expression referencing base CSI. */
+	stree_texpr_t *base_csi_ref;
+
+	/** Node state for ancr walks. */
+	walk_state_t ancr_state;
+
+	/** List of CSI members */
+	list_t members; /* of stree_csimbr_t */
+} stree_csi_t;
+
+typedef enum {
+	/* Class, struct or interface declaration */
+	mc_csi
+} modm_class_t;
+
+/** Module member */
+typedef struct {
+	modm_class_t mc;
+	union {
+		stree_csi_t *csi;
+	} u;
+} stree_modm_t;
+
+/** Module */
+typedef struct stree_module {
+	/** List of module members */
+	list_t members; /* of stree_modm_t */
+} stree_module_t;
+
+typedef enum {
+	sc_csi,
+	sc_fun,
+	sc_var,
+	sc_prop
+} symbol_class_t;
+
+/** Symbol */
+typedef struct stree_symbol {
+	symbol_class_t sc;
+
+	union {
+		struct stree_csi *csi;
+		stree_fun_t *fun;
+		stree_var_t *var;
+		stree_prop_t *prop;
+	} u;
+
+	/** Containing CSI (for all symbols) */
+	stree_csi_t *outer_csi;
+
+	/** Containing block (for block-level symbols) */
+	stree_block_t *outer_block;
+} stree_symbol_t;
+
+/** Program */
+typedef struct stree_program {
+	/** The one and only module in the program */
+	stree_module_t *module;
+} stree_program_t;
+
+#endif
Index: uspace/app/sbi/src/strtab.c
===================================================================
--- uspace/app/sbi/src/strtab.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/strtab.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file String table.
+ *
+ * Converts strings to more compact SID (string ID, integer) and back.
+ * The string table is not an object as there will never be a need for
+ * more than one.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "mytypes.h"
+#include "compat.h"
+#include "list.h"
+
+#include "strtab.h"
+
+static list_t str_list;
+
+void strtab_init(void)
+{
+	list_init(&str_list);
+}
+
+sid_t strtab_get_sid(char *str)
+{
+	list_node_t *node;
+	sid_t sid;
+
+	sid = 0;
+	node = list_first(&str_list);
+
+	while (node != NULL) {
+		++sid;
+		if (strcmp(str, list_node_data(node, char *)) == 0)
+			return sid;
+
+		node = list_next(&str_list, node);
+	}
+
+	++sid;
+	list_append(&str_list, strdup(str));
+
+	return sid;
+}
+
+char *strtab_get_str(sid_t sid)
+{
+	list_node_t *node;
+	sid_t cnt;
+
+	node = list_first(&str_list);
+	cnt = 1;
+	while (node != NULL && cnt < sid) {
+		node = list_next(&str_list, node);
+		cnt += 1;
+	}
+
+	if (node == NULL) {
+		printf("Internal error: Invalid SID %d", sid);
+		exit(1);
+	}
+
+	return list_node_data(node, char *);
+}
Index: uspace/app/sbi/src/strtab.h
===================================================================
--- uspace/app/sbi/src/strtab.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/strtab.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STRTAB_H_
+#define STRTAB_H_
+
+#include "mytypes.h"
+
+void strtab_init(void);
+sid_t strtab_get_sid(char *str);
+char *strtab_get_str(sid_t sid);
+
+#endif
Index: uspace/app/sbi/src/strtab_t.h
===================================================================
--- uspace/app/sbi/src/strtab_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/strtab_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STRTAB_T_H_
+#define STRTAB_T_H_
+
+/** String ID */
+typedef int sid_t;
+
+#endif
Index: uspace/app/sbi/src/symbol.c
===================================================================
--- uspace/app/sbi/src/symbol.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/symbol.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Symbols. */
+
+#include <stdlib.h>
+#include <assert.h>
+#include "list.h"
+#include "mytypes.h"
+#include "strtab.h"
+#include "stree.h"
+
+#include "symbol.h"
+
+static stree_symbol_t *symbol_search_global(stree_program_t *prog,
+    stree_ident_t *name);
+static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol);
+
+/** Lookup symbol in CSI using a type expression. */
+stree_symbol_t *symbol_xlookup_in_csi(stree_program_t *prog,
+    stree_csi_t *scope, stree_texpr_t *texpr)
+{
+	stree_symbol_t *a, *b;
+	stree_csi_t *a_csi;
+
+	switch (texpr->tc) {
+	case tc_tnameref:
+		return symbol_lookup_in_csi(prog, scope, texpr->u.tnameref->name);
+	case tc_taccess:
+		a = symbol_xlookup_in_csi(prog, scope, texpr->u.taccess->arg);
+		a_csi = symbol_to_csi(a);
+		if (a_csi == NULL) {
+			printf("Error: Symbol is not CSI.\n");
+			exit(1);
+		}
+		b = symbol_search_csi(prog, a_csi, texpr->u.taccess->member_name);
+		if (b == NULL) {
+			printf("Error: CSI '%s' not found\n", strtab_get_str(texpr->u.taccess->member_name->sid));
+			exit(1);
+		}
+		return b;
+	case tc_tapply:
+		printf("Internal error: Generic types not implemented.\n");
+		exit(1);
+	default:
+		assert(b_false);
+	}
+}
+
+/** Lookup symbol reference in CSI. */
+stree_symbol_t *symbol_lookup_in_csi(stree_program_t *prog, stree_csi_t *scope,
+	stree_ident_t *name)
+{
+	stree_symbol_t *symbol;
+
+	/* This CSI node should have been processed. */
+	assert(scope == NULL || scope->ancr_state == ws_visited);
+
+	symbol = NULL;
+	while (scope != NULL && symbol == NULL) {
+		symbol = symbol_search_csi(prog, scope, name);
+		scope = csi_to_symbol(scope)->outer_csi;
+	}
+
+	if (symbol == NULL)
+		symbol = symbol_search_global(prog, name);
+
+	if (symbol == NULL) {
+		printf("Error: Symbol '%s' not found\n", strtab_get_str(name->sid));
+		exit(1);
+	}
+
+	return symbol;
+}
+
+/** Look for symbol strictly in CSI.
+ *
+ * Look for symbol in definition of a CSI and its ancestors. (But not
+ * in lexically enclosing CSI.)
+ */
+stree_symbol_t *symbol_search_csi(stree_program_t *prog,
+    stree_csi_t *scope, stree_ident_t *name)
+{
+	list_node_t *node;
+	stree_csimbr_t *csimbr;
+	stree_symbol_t *symbol;
+	stree_ident_t *mbr_name;
+
+	node = list_first(&scope->members);
+	while (node != NULL) {
+		csimbr = list_node_data(node, stree_csimbr_t *);
+		switch (csimbr->cc) {
+		case csimbr_csi: mbr_name = csimbr->u.csi->name; break;
+		case csimbr_fun: mbr_name = csimbr->u.fun->name; break;
+		case csimbr_var: mbr_name = csimbr->u.var->name; break;
+		case csimbr_prop: mbr_name = csimbr->u.prop->name; break;
+		default: assert(b_false);
+		}
+
+		if (name->sid == mbr_name->sid) {
+			/* Match */
+			switch (csimbr->cc) {
+			case csimbr_csi:
+				symbol = csi_to_symbol(csimbr->u.csi);
+				break;
+			case csimbr_fun:
+				symbol = fun_to_symbol(csimbr->u.fun);
+				break;
+			case csimbr_var:
+				symbol = var_to_symbol(csimbr->u.var);
+				break;
+			case csimbr_prop:
+				symbol = prop_to_symbol(csimbr->u.prop);
+				break;
+			default:
+				assert(b_false);
+			}
+			return symbol;
+		}
+		node = list_next(&scope->members, node);
+	}
+
+	return NULL;
+}
+
+static stree_symbol_t *symbol_search_global(stree_program_t *prog,
+    stree_ident_t *name)
+{
+	list_node_t *node;
+	stree_modm_t *modm;
+	stree_symbol_t *symbol;
+
+	node = list_first(&prog->module->members);
+	while (node != NULL) {
+		modm = list_node_data(node, stree_modm_t *);
+		if (name->sid == modm->u.csi->name->sid) {
+			/* Match */
+			switch (modm->mc) {
+			case mc_csi:
+				symbol = csi_to_symbol(modm->u.csi);
+				break;
+			default:
+				assert(b_false);
+			}
+			return symbol;
+		}
+		node = list_next(&prog->module->members, node);
+	}
+
+	return NULL;
+}
+
+stree_csi_t *symbol_to_csi(stree_symbol_t *symbol)
+{
+	if (symbol->sc != sc_csi)
+		return NULL;
+
+	return symbol->u.csi;
+}
+
+stree_symbol_t *csi_to_symbol(stree_csi_t *csi)
+{
+	assert(csi->symbol);
+	return csi->symbol;
+}
+
+stree_fun_t *symbol_to_fun(stree_symbol_t *symbol)
+{
+	if (symbol->sc != sc_fun)
+		return NULL;
+
+	return symbol->u.fun;
+}
+
+stree_symbol_t *fun_to_symbol(stree_fun_t *fun)
+{
+	assert(fun->symbol);
+	return fun->symbol;
+}
+
+stree_var_t *symbol_to_var(stree_symbol_t *symbol)
+{
+	if (symbol->sc != sc_var)
+		return NULL;
+
+	return symbol->u.var;
+}
+
+stree_symbol_t *var_to_symbol(stree_var_t *var)
+{
+	assert(var->symbol);
+	return var->symbol;
+}
+
+stree_prop_t *symbol_to_prop(stree_symbol_t *symbol)
+{
+	if (symbol->sc != sc_prop)
+		return NULL;
+
+	return symbol->u.prop;
+}
+
+stree_symbol_t *prop_to_symbol(stree_prop_t *prop)
+{
+	assert(prop->symbol);
+	return prop->symbol;
+}
+
+/** Print fully qualified name of symbol. */
+void symbol_print_fqn(stree_program_t *prog, stree_symbol_t *symbol)
+{
+	stree_ident_t *name;
+	stree_symbol_t *outer_sym;
+
+	if (symbol->outer_csi != NULL) {
+		outer_sym = csi_to_symbol(symbol->outer_csi);
+		symbol_print_fqn(prog, outer_sym);
+		printf(".");
+	}
+
+	name = symbol_get_ident(symbol);
+	printf("%s", strtab_get_str(name->sid));
+}
+
+static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol)
+{
+	stree_ident_t *ident;
+
+	switch (symbol->sc) {
+	case sc_csi: ident = symbol->u.csi->name; break;
+	case sc_fun: ident = symbol->u.fun->name; break;
+	case sc_var: ident = symbol->u.var->name; break;
+	case sc_prop: ident = symbol->u.prop->name; break;
+	}
+
+	return ident;
+}
Index: uspace/app/sbi/src/symbol.h
===================================================================
--- uspace/app/sbi/src/symbol.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/symbol.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYMBOL_H_
+#define SYMBOL_H_
+
+#include "mytypes.h"
+
+stree_symbol_t *symbol_xlookup_in_csi(stree_program_t *prog,
+    stree_csi_t *scope, stree_texpr_t *texpr);
+stree_symbol_t *symbol_lookup_in_csi(stree_program_t *prog, stree_csi_t *scope,
+    stree_ident_t *name);
+stree_symbol_t *symbol_search_csi(stree_program_t *prog, stree_csi_t *scope,
+    stree_ident_t *name);
+
+
+stree_csi_t *symbol_to_csi(stree_symbol_t *symbol);
+stree_symbol_t *csi_to_symbol(stree_csi_t *csi);
+stree_fun_t *symbol_to_fun(stree_symbol_t *symbol);
+stree_symbol_t *fun_to_symbol(stree_fun_t *fun);
+stree_var_t *symbol_to_var(stree_symbol_t *symbol);
+stree_symbol_t *var_to_symbol(stree_var_t *var);
+stree_prop_t *symbol_to_prop(stree_symbol_t *symbol);
+stree_symbol_t *prop_to_symbol(stree_prop_t *prop);
+
+void symbol_print_fqn(stree_program_t *prog, stree_symbol_t *symbol);
+
+#endif
