Add a simple S-Expression reader and printer.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 7 Apr 2010 20:39:34 +0000 (13:39 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 29 Apr 2010 01:14:36 +0000 (18:14 -0700)
Makefile.am
s_expression.cpp [new file with mode: 0644]
s_expression.h [new file with mode: 0644]

index b43dee3..4312d41 100644 (file)
@@ -36,7 +36,8 @@ glsl_SOURCES = \
        ir_expression_flattening.cpp \
        ir_function_can_inline.cpp \
        ir_function_inlining.cpp \
-       ir_if_simplification.cpp
+       ir_if_simplification.cpp \
+       s_expression.cpp
 
 BUILT_SOURCES = glsl_parser.h glsl_parser.cpp glsl_lexer.cpp
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/s_expression.cpp b/s_expression.cpp
new file mode 100644 (file)
index 0000000..4022dfa
--- /dev/null
@@ -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(")");
+}
+
diff --git a/s_expression.h b/s_expression.h
new file mode 100644 (file)
index 0000000..d5e52c1
--- /dev/null
@@ -0,0 +1,148 @@
+/* -*- 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.
+ */
+
+#pragma once
+#ifndef S_EXPRESSION_H
+#define S_EXPRESSION_H
+
+#include "list.h"
+
+#define SX_AS_(t,x) ((x) && ((s_expression*) x)->is_##t()) ? ((s_##t*) (x)) \
+                                                           : NULL
+#define SX_AS_LIST(x)   SX_AS_(list, x)
+#define SX_AS_SYMBOL(x) SX_AS_(symbol, x)
+#define SX_AS_NUMBER(x) SX_AS_(number, x)
+#define SX_AS_INT(x)    SX_AS_(int, x)
+
+/* For our purposes, S-Expressions are:
+ * - <int>
+ * - <float>
+ * - symbol
+ * - (expr1 expr2 ... exprN)     where exprN is an S-Expression
+ *
+ * Unlike LISP/Scheme, we do not support (foo . bar) pairs.
+ */
+class s_expression : public exec_node
+{
+public:
+   virtual ~s_expression() { }
+
+   /**
+    * Read an S-Expression from the given string.
+    * Advances the supplied pointer to just after the expression read.
+    */
+   static s_expression *read_expression(const char *&src);
+
+   /**
+    * Print out an S-Expression.  Useful for debugging.
+    */
+   virtual void print() = 0;
+
+   virtual bool is_list()   const { return false; }
+   virtual bool is_symbol() const { return false; }
+   virtual bool is_number() const { return false; }
+   virtual bool is_int()    const { return false; }
+
+protected:
+   s_expression() { }
+};
+
+/* Atoms */
+
+class s_number : public s_expression
+{
+public:
+   virtual ~s_number() { }
+
+   bool is_number() const { return true; }
+
+   virtual float fvalue() = 0;
+
+protected:
+   s_number() { }
+};
+
+class s_int : public s_number
+{
+public:
+   s_int(int x) : val(x) { }
+   virtual ~s_int() { }
+
+   bool is_int() const { return true; }
+
+   float fvalue() { return float(this->val); }
+   int value() { return this->val; }
+
+   void print();
+
+private:
+   int val;
+};
+
+class s_float : public s_number
+{
+public:
+   s_float(float x) : val(x) { }
+   virtual ~s_float() { }
+
+   float fvalue() { return this->val; }
+
+   void print();
+
+private:
+   float val;
+};
+
+class s_symbol : public s_expression
+{
+public:
+   s_symbol(const char *);
+   virtual ~s_symbol();
+
+   bool is_symbol() const { return true; }
+
+   const char *value() { return this->str; }
+
+   void print();
+
+private:
+   char *str;
+};
+
+/* Lists of expressions: (expr1 ... exprN) */
+class s_list : public s_expression
+{
+public:
+   s_list();
+   virtual ~s_list();
+
+   virtual bool is_list() const { return true; }
+   unsigned length() const;
+
+   void print();
+
+   exec_list subexpressions;
+};
+
+#endif /* S_EXPRESSION_H */