diff options
author | Kenneth Graunke <kenneth@whitecape.org> | 2010-04-07 13:39:34 -0700 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2010-04-28 18:14:36 -0700 |
commit | 1bfe1c3fdde39235ccbd8fc3da84a1603e919bc3 (patch) | |
tree | f9407a2869ba2ebfeae7c6d262af47de6f9e2adf /s_expression.cpp | |
parent | 9d290d786d702cfc5eb7b6aefd6cb5b2c946ab88 (diff) |
Add a simple S-Expression reader and printer.
Diffstat (limited to 's_expression.cpp')
-rw-r--r-- | s_expression.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
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(")"); +} + |