From 1bfe1c3fdde39235ccbd8fc3da84a1603e919bc3 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 7 Apr 2010 13:39:34 -0700 Subject: [PATCH] Add a simple S-Expression reader and printer. --- Makefile.am | 3 +- s_expression.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++ s_expression.h | 148 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 s_expression.cpp create mode 100644 s_expression.h diff --git a/Makefile.am b/Makefile.am index b43dee3037e..4312d41980e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 index 00000000000..4022dfab7a7 --- /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 +#include +#include +#include +#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 index 00000000000..d5e52c16e83 --- /dev/null +++ b/s_expression.h @@ -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: + * - + * - + * - 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 */ -- 2.30.2