Add a simple S-Expression reader and printer.
diff --git a/s_expression.cpp b/s_expression.cpp
new file mode 100644
index 0000000..4022dfa
--- /dev/null
+++ b/s_expression.cpp
@@ -0,0 +1,146 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <assert.h>
+#include "s_expression.h"
+
+s_symbol::s_symbol(const char *tmp)
+{
+   this->str = new char [strlen(tmp) + 1];
+   strcpy(this->str, tmp);
+}
+
+s_symbol::~s_symbol()
+{
+   delete [] this->str;
+   this->str = NULL;
+}
+
+s_list::s_list()
+{
+}
+
+s_list::~s_list()
+{
+   exec_list_iterator it(this->subexpressions.iterator());
+   while (it.has_next())
+      it.remove();
+
+   assert(this->subexpressions.is_empty());
+}
+
+unsigned
+s_list::length() const
+{
+   unsigned i = 0;
+   foreach_iter(exec_list_iterator, it, this->subexpressions) {
+      i++;
+   }
+   return i;
+}
+
+static s_expression *
+read_atom(const char *& src)
+{
+   char buf[101];
+   int n;
+   if (sscanf(src, " %100[^( \v\t\r\n)]%n", buf, &n) != 1)
+      return NULL; // no atom
+   src += n;
+
+   // Check if the atom is a number.
+   char *float_end = NULL;
+   double f = strtod(buf, &float_end);
+   if (float_end != buf) {
+      char *int_end = NULL;
+      int i = strtol(buf, &int_end, 10);
+      // If strtod matched more characters, it must have a decimal part
+      if (float_end > int_end)
+	 return new s_float(f);
+
+      return new s_int(i);
+   }
+   // Not a number; return a symbol.
+   return new s_symbol(buf);
+}
+
+s_expression *
+s_expression::read_expression(const char *&src)
+{
+   assert(src != NULL);
+
+   s_expression *atom = read_atom(src);
+   if (atom != NULL)
+      return atom;
+
+   char c;
+   int n;
+   if (sscanf(src, " %c%n", &c, &n) == 1 && c == '(') {
+      src += n;
+
+      s_list *list = new s_list;
+      s_expression *expr;
+
+      while ((expr = read_expression(src)) != NULL) {
+	 list->subexpressions.push_tail(expr);
+      }
+      if (sscanf(src, " %c%n", &c, &n) != 1 || c != ')') {
+	 printf("Unclosed expression (check your parenthesis).\n");
+	 return NULL;
+      }
+      src += n;
+      return list;
+   }
+   return NULL;
+}
+
+void s_int::print()
+{
+   printf("%d", this->val);
+}
+
+void s_float::print()
+{
+   printf("%f", this->val);
+}
+
+void s_symbol::print()
+{
+   printf("%s", this->str);
+}
+
+void s_list::print()
+{
+   printf("(");
+   foreach_iter(exec_list_iterator, it, this->subexpressions) {
+      s_expression *expr = (s_expression*) it.get();
+      expr->print();
+      printf(" ");
+   }
+   printf(")");
+}
+