summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2008-05-15 23:28:07 +0000
committerPaul Buetow <paul@buetow.org>2008-05-15 23:28:07 +0000
commitbe839900419c7a74c4a46efd279d0ca16b35dc1f (patch)
tree1355c8f238d1c58ffd5cb8803bcc2adf987e79aa /src/core
parent33c945e58f86267b0d3bdca4c3421155e11eb0d9 (diff)
Moved stuff into trunk.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/convert.c185
-rw-r--r--src/core/convert.h53
-rw-r--r--src/core/function.c661
-rw-r--r--src/core/function.h50
-rw-r--r--src/core/garbage.c136
-rw-r--r--src/core/garbage.h54
-rw-r--r--src/core/interpret.c946
-rw-r--r--src/core/interpret.h75
-rw-r--r--src/core/scanner.c391
-rw-r--r--src/core/scanner.h71
-rw-r--r--src/core/scope.c150
-rw-r--r--src/core/scope.h59
-rw-r--r--src/core/symbol.c66
-rw-r--r--src/core/symbol.h64
-rw-r--r--src/core/token.c380
-rw-r--r--src/core/token.h183
16 files changed, 3524 insertions, 0 deletions
diff --git a/src/core/convert.c b/src/core/convert.c
new file mode 100644
index 0000000..0d63619
--- /dev/null
+++ b/src/core/convert.c
@@ -0,0 +1,185 @@
+/*:*
+ *: File: ./src/core/convert.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "convert.h"
+
+void
+convert_to_integer(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ break;
+ case TT_DOUBLE:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, (int)token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, atoi(token_get_val(p_token)));
+ break;
+ default:
+ ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token)));
+ break;
+ }
+}
+
+int
+convert_to_integer_get(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ return (token_get_ival(p_token));
+ case TT_DOUBLE:
+ return ((int) token_get_dval(p_token));
+ case TT_STRING:
+ return (atoi(token_get_val(p_token)));
+ default:
+ ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token)));
+ }
+
+ return (0); /* Never reach this point */
+}
+
+void
+convert_to_double(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ break;
+ case TT_STRING:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, atof(token_get_val(p_token)));
+ break;
+ default:
+ token_print_val(p_token);
+ ERROR("Datatype conversion error '%s'", token_get_val(p_token));
+ break;
+ }
+}
+
+void
+convert_to_string(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%d", token_get_ival(p_token));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ break;
+ case TT_DOUBLE:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%f", token_get_dval(p_token));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ break;
+ case TT_STRING:
+ break;
+ default:
+ ERROR("Datatype conversion error");
+ break;
+ }
+}
+
+void
+convert_to_tt(Token *p_token, TokenType tt) {
+ switch (tt) {
+ case TT_INTEGER:
+ convert_to_integer(p_token);
+ break;
+ case TT_DOUBLE:
+ convert_to_double(p_token);
+ break;
+ case TT_STRING:
+ convert_to_string(p_token);
+ break;
+ default:
+ ERROR("Ouups!");
+ }
+}
+
+TokenType
+convert_to_highest(Token *p_token1, Token *p_token2) {
+ TokenType tt_highest = token_get_tt(p_token1);
+
+ if (tt_highest < token_get_tt(p_token2)) {
+ tt_highest = token_get_tt(p_token2);
+
+ convert_to_tt(p_token1, tt_highest);
+
+ } else {
+ convert_to_tt(p_token2, tt_highest);
+ }
+
+ return (tt_highest);
+}
+
+TokenType
+convert_function_arg_types_to_highest(Stack *p_stack_args, int i_args) {
+
+ if (i_args <= 0)
+ i_args = stack_size(p_stack_args);
+
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ TokenType tt_highest = TT_INTEGER;
+
+ for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) {
+ Token *p_token = stackiterator_next(p_iter);
+ if (token_get_tt(p_token) > tt_highest)
+ tt_highest = token_get_tt(p_token);
+ }
+
+ stackiterator_delete(p_iter);
+ p_iter = stackiterator_new(p_stack_args);
+
+ for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) {
+ Token *p_token = stackiterator_next(p_iter);
+ convert_to_tt(p_token, tt_highest);
+ }
+
+ stackiterator_delete(p_iter);
+
+ return (tt_highest);
+}
+
diff --git a/src/core/convert.h b/src/core/convert.h
new file mode 100644
index 0000000..c4e0b1d
--- /dev/null
+++ b/src/core/convert.h
@@ -0,0 +1,53 @@
+/*:*
+ *: File: ./src/core/convert.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 CONVERT_H
+#define CONVERT_H
+
+#include "../defines.h"
+
+#include "../data/stack.h"
+
+#include "token.h"
+
+int convert_to_integer_get(Token *p_token);
+void convert_to_integer(Token *p_token);
+void convert_to_double(Token *p_token);
+void convert_to_string(Token *p_token);
+void convert_to_tt(Token *p_token, TokenType tt);
+TokenType convert_to_highest(Token *p_token1, Token *p_token2);
+TokenType convert_function_arg_types_to_highest(Stack *p_stack_args, int
+ i_args);
+
+#endif
diff --git a/src/core/function.c b/src/core/function.c
new file mode 100644
index 0000000..fd18ba0
--- /dev/null
+++ b/src/core/function.c
@@ -0,0 +1,661 @@
+/*:*
+ *: File: ./src/core/function.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "function.h"
+
+#include "convert.h"
+#include "scope.h"
+#include "symbol.h"
+
+#define _FUNCTION_ERROR(m,t) \
+ ERROR(\
+ "%s: Function error in %s line %d pos %d near '%s'", m, \
+ token_get_filename(t), \
+ token_get_line_nr(t), \
+ token_get_pos_nr(t), \
+ token_get_val(t) \
+ )
+
+void
+_process(Interpret *p_interpret, Token *p_token_store, Token *p_token_op,
+ Token *p_token_next) {
+
+ TokenType tt_op = token_get_tt(p_token_op);
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ printf("PROCESS OPERATOR %s\n", tt_get_name(tt_op));
+
+ token_print(p_token_next);
+ printf("\n");
+ token_print(p_token_store);
+ printf("\n");
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+
+ switch (tt_op) {
+ case TT_ASSIGN:
+ {
+ Token *p_token_assign = p_interpret->p_token_temp;
+ TokenType tt_assign = token_get_tt(p_token_assign);
+
+ if (tt_assign != TT_IDENT) {
+ _FUNCTION_ERROR("Can only assign to symbols",
+ p_token_store);
+ }
+
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_token_assign));
+
+ if (p_symbol == NULL) {
+ _FUNCTION_ERROR("No such symbol",
+ p_token_assign);
+ }
+
+ symbol_set_val(p_symbol, p_token_store);
+ symbol_set_sym(p_symbol, SYM_VARIABLE);
+
+ return;
+ }
+
+ break;
+ NO_DEFAULT;
+ }
+
+ p_token_next = token_new_copy(p_token_next);
+ TokenType tt_highest = convert_to_highest(p_token_store, p_token_next);
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ printf("===> %s %s %s\n",
+ tt_get_name(tt_highest),
+ tt_get_name(tt_op),
+ tt_get_name(tt_highest));
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ switch (tt_op) {
+ case TT_ADD:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) +
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) +
+ token_get_dval(p_token_store));
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) +
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_SUB:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) -
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) -
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) -
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_MULT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) *
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) *
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) *
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_DIV:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) /
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) /
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_dval(p_token_store,
+ atof(token_get_val(p_token_next)) /
+ atof(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_DOUBLE);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_EQ:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) ==
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) ==
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) == 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_NEQ:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) !=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) !=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) != 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) <
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) < 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_GT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) >
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) > 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LE:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) <=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) <= 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_GE:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) >=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) >= 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ default:
+ _FUNCTION_ERROR("No such function/operator", p_token_op);
+ }
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ token_print(p_token_store);
+ printf("\n\n");
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ token_delete(p_token_next);
+}
+
+void
+function_process(Interpret *p_interpret, Token *p_token_op,
+ Stack *p_stack_args, int i_args) {
+
+ Token *p_token_store = token_new_copy(stack_pop(p_stack_args));
+
+ for (int i = 0; i < i_args -1 && !stack_empty(p_stack_args); ++i) {
+ Token *p_token_next = stack_pop(p_stack_args);
+
+ _process(p_interpret, p_token_store, p_token_op, p_token_next);
+ }
+
+ stack_push(p_stack_args, p_token_store);
+}
+
+_Bool
+function_is_buildin(Token *p_token_ident) {
+ if (strcmp("assert", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("decr", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("double", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("end", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("exit", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("fork", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("gc", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("incr", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("integer", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("ln", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("neg", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("no", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("put", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("say", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("string", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("yes", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ return (false);
+}
+
+void
+function_process_buildin(Interpret *p_interpret, Token *p_token_ident,
+ Stack *p_stack_args) {
+
+ if (strcmp("assert", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ if (token_get_ival(p_token) == 0)
+ _FUNCTION_ERROR("Assert failed", p_token);
+ break;
+ case TT_DOUBLE:
+ if (token_get_dval(p_token) == 0)
+ _FUNCTION_ERROR("Assert failed", p_token);
+ break;
+ case TT_STRING:
+ if (atoi(token_get_val(p_token)) == 0)
+ _FUNCTION_ERROR("Assert failed", p_token);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("decr", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, token_get_ival(p_token) - 1);
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, token_get_dval(p_token) - 1);
+ break;
+ case TT_STRING:
+ convert_to_integer(p_token);
+ token_set_ival(p_token, token_get_ival(p_token) - 1);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("double", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_double(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("end", token_get_val(p_token_ident)) == 0) {
+ exit(0);
+
+ } else if (strcmp("fork", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = token_new_integer((int) fork());
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("gc", token_get_val(p_token_ident)) == 0) {
+ int i_count = garbage_collect();
+ printf("ICOUNT %d\n", i_count);
+ Token *p_token = token_new_integer(i_count);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("exit", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+ p_token = token_new_copy(p_token);
+ convert_to_integer(p_token);
+ exit(token_get_ival(p_token));
+
+ } else if (strcmp("incr", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, token_get_ival(p_token) + 1);
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, token_get_dval(p_token) + 1);
+ break;
+ case TT_STRING:
+ convert_to_integer(p_token);
+ token_set_ival(p_token, token_get_ival(p_token) + 1);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("integer", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_integer(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("ln", token_get_val(p_token_ident)) == 0) {
+ printf("\n");
+
+ } else if (strcmp("neg", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ stack_push(p_stack_args, p_token);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, -token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, -token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, -atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("no", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = NULL;
+
+ if (0 == stack_size(p_stack_args)) {
+ p_token = token_new_integer(0);
+
+ } else {
+ p_token = token_new_copy(stack_pop(p_stack_args));
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, !token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, !token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, !atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ }
+
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("put", token_get_val(p_token_ident)) == 0) {
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ while (stackiterator_has_next(p_iter)) {
+ Token *p_token = stackiterator_next(p_iter);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ printf("%d", token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("%f", token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("%s", token_get_val(p_token));
+ break;
+ NO_DEFAULT;
+ }
+ }
+ stackiterator_delete(p_iter);
+
+ } else if (strcmp("say", token_get_val(p_token_ident)) == 0) {
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ while (stackiterator_has_next(p_iter)) {
+ Token *p_token = stackiterator_next(p_iter);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ printf("%d", token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("%f", token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("%s", token_get_val(p_token));
+ break;
+ NO_DEFAULT;
+ }
+ }
+ stackiterator_delete(p_iter);
+ printf("\n");
+
+ } else if (strcmp("string", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_string(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("yes", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = NULL;
+
+ if (0 == stack_size(p_stack_args)) {
+ p_token = token_new_integer(1);
+
+ } else {
+ p_token = token_new_copy(stack_pop(p_stack_args));
+ token_set_ival(p_token, 1);
+ token_set_tt(p_token, TT_INTEGER);
+
+ }
+
+ stack_push(p_stack_args, p_token);
+ }
+}
+
+_Bool
+function_is_self_defined(Interpret *p_interpret) {
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_interpret->p_token));
+
+ if (p_symbol == NULL)
+ return (false);
+
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ case SYM_FUNCTION:
+ return (true);
+ NO_DEFAULT;
+ }
+
+ return (false);
+}
+
+void
+function_process_self_defined(Interpret *p_interpret, Token *p_token_ident) {
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_token_ident));
+
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ interpret_subprocess(p_interpret, p_list_token);
+ }
+ break;
+ case SYM_FUNCTION:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_token);
+ scope_down(p_interpret->p_scope);
+ }
+ NO_DEFAULT;
+ }
+}
+
diff --git a/src/core/function.h b/src/core/function.h
new file mode 100644
index 0000000..9f12bb4
--- /dev/null
+++ b/src/core/function.h
@@ -0,0 +1,50 @@
+/*:*
+ *: File: ./src/core/function.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 FUNCTION_H
+#define FUNCTION_H
+
+#include "token.h"
+
+#include "interpret.h"
+#include "../data/stack.h"
+
+void function_process(Interpret *p_interp, Token *p_token_op, Stack
+ *p_stack_args, int i_args);
+_Bool function_is_buildin(Token *p_token_ident);
+void function_process_buildin(Interpret *p_interpret, Token *p_token_ident, Stack *p_stack_args);
+_Bool function_is_self_defined(Interpret *p_interpret);
+void function_process_self_defined(Interpret *p_interpret, Token *p_token_ident);
+
+#endif /* FUNCTION_H */
diff --git a/src/core/garbage.c b/src/core/garbage.c
new file mode 100644
index 0000000..b4dad22
--- /dev/null
+++ b/src/core/garbage.c
@@ -0,0 +1,136 @@
+/*:*
+ *: File: ./src/core/garbage.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "garbage.h"
+
+#define _GARBAGE_ERROR(m) \
+ ERROR("%s: Garbage error", m);
+
+List *LIST_GARBAGE = NULL;
+
+typedef struct {
+ void (*p_func)(void*);
+ int *p_ref_count;
+ void *p_2free;
+ GarbageType type;
+} _Garbage;
+
+void
+garbage_init() {
+ LIST_GARBAGE = list_new();
+}
+
+void
+_garbage_print(_Garbage *p_garbage) {
+ switch (p_garbage->type) {
+ case GC_TOKEN:
+ {
+ Token *p_token = p_garbage->p_2free;
+ token_print(p_token);
+ printf("\n");
+ }
+ break;
+ }
+}
+
+void
+garbage_destroy() {
+ garbage_collect();
+
+ if (!list_empty(LIST_GARBAGE)) {
+ EPRINTF("The garbage collector still has %d registered items which don't have"
+ " a zero ref count!\n", list_size(LIST_GARBAGE));
+
+ ListIterator *p_iter = listiterator_new(LIST_GARBAGE);
+ while (listiterator_has_next(p_iter)) {
+ _Garbage *p_garbage = listiterator_next(p_iter);
+ _garbage_print(p_garbage);
+ }
+ listiterator_delete(p_iter);
+
+ _GARBAGE_ERROR("Garbage left");
+ }
+
+ list_delete(LIST_GARBAGE);
+}
+
+int
+garbage_collect() {
+ ListIterator *p_iter = listiterator_new(LIST_GARBAGE);
+ List *p_list_garbage_new = list_new();
+ int i_count = 0;
+
+ while (listiterator_has_next(p_iter)) {
+ _Garbage *p_garbage = listiterator_next(p_iter);
+
+ if (p_garbage->p_ref_count == NULL || *p_garbage->p_ref_count <= 0) {
+ // _garbage_print(p_garbage);
+ (*p_garbage->p_func) (p_garbage->p_2free);
+ free(p_garbage);
+ ++i_count;
+
+ } else {
+ list_add_back(p_list_garbage_new, p_garbage);
+ }
+ }
+
+ listiterator_delete(p_iter);
+
+ list_delete(LIST_GARBAGE);
+ LIST_GARBAGE = p_list_garbage_new;
+
+ return (i_count);
+}
+
+void
+garbage_add(void *p, GarbageType type) {
+ garbage_add2(p, free, NULL, type);
+}
+
+void
+garbage_add2(void *p, void (*p_func)(void*), int *p_ref_count, GarbageType type) {
+ _Garbage *p_garbage = malloc(sizeof(_Garbage));
+
+ p_garbage->p_2free = p;
+ p_garbage->p_func = p_func;
+ p_garbage->p_ref_count = p_ref_count;
+ p_garbage->type = type;
+
+ list_add_back(LIST_GARBAGE, p_garbage);
+}
+
+void
+garbage_add_token(Token *p_token) {
+ garbage_add2(p_token, token_delete_cb, &p_token->i_ref_count, GC_TOKEN);
+}
diff --git a/src/core/garbage.h b/src/core/garbage.h
new file mode 100644
index 0000000..6a8007d
--- /dev/null
+++ b/src/core/garbage.h
@@ -0,0 +1,54 @@
+/*:*
+ *: File: ./src/core/garbage.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 GARBAGE_H
+#define GARBAGE_H
+
+#include "../defines.h"
+#include "../data/list.h"
+#include "token.h"
+
+typedef enum {
+ GC_TOKEN,
+} GarbageType;
+
+void garbage_init();
+void garbage_destroy();
+int garbage_collect();
+void garbage_add(void *p, GarbageType type);
+void garbage_add2(void *p, void (*p_func)(void*), int *p_ref_count,
+ GarbageType type);
+void garbage_add_token(Token *p_token);
+
+#endif
diff --git a/src/core/interpret.c b/src/core/interpret.c
new file mode 100644
index 0000000..97e19c2
--- /dev/null
+++ b/src/core/interpret.c
@@ -0,0 +1,946 @@
+/*:*
+ *: File: ./src/core/interpret.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "interpret.h"
+
+#include "../defines.h"
+#include "convert.h"
+#include "function.h"
+#include "symbol.h"
+
+#define _INTERPRET_ERROR(m,t) \
+ ERROR(\
+ "%s: Interpret error in %s line %d pos %d near '%s'", m, \
+ token_get_filename(t), \
+ token_get_line_nr(t), \
+ token_get_pos_nr(t), \
+ token_get_val(t) \
+ )
+
+#define _CHECK if (p_interpret->p_token == NULL) return (0);
+#define _HAS_NEXT listiterator_has_next(p_interpret->p_iter)
+#define _NEXT if (!_next(p_interpret)) { return (2); }
+#define _NEXT_TT _next_tt(p_interpret)
+#define _SKIP _next(p_interpret);
+
+void _print_lookahead(Interpret *p_interpret);
+int _next(Interpret *p_interpret);
+int _program(Interpret *p_interpret);
+int _var_decl(Interpret *p_interpret);
+int _var_assign(Interpret *p_interpret);
+int _var_list(Interpret *p_interpret);
+int _expression_get(Interpret *p_interpret, List *p_list_block);
+int _block_get(Interpret *p_interpret, List *p_list_block);
+int _block_skip(Interpret *p_interpret);
+int _proc_decl(Interpret *p_interpret);
+int _func_decl(Interpret *p_interpret);
+int _statement(Interpret *p_interpret);
+int _block(Interpret *p_interpret);
+int _expression(Interpret *p_interpret);
+int _expression_(Interpret *p_interpret);
+int _control(Interpret *p_interpret);
+int _compare(Interpret *p_interpret);
+int _sum(Interpret *p_interpret);
+int _product(Interpret *p_interpret);
+int _product2(Interpret *p_interpret);
+int _term(Interpret *p_interpret);
+
+Interpret*
+interpret_new(List *p_list_token, Hash *p_hash_syms) {
+ Interpret *p_interpret = malloc(sizeof(Interpret));
+
+ if (p_hash_syms != NULL) {
+ p_interpret->p_scope = scope_new(p_hash_syms);
+ p_interpret->b_scope_delete = true;
+
+ } else {
+ p_interpret->p_scope = NULL;
+ p_interpret->b_scope_delete = false;
+ }
+
+ p_interpret->p_list_token = p_list_token;
+ p_interpret->p_stack = stack_new();
+ p_interpret->tt = TT_NONE;
+ p_interpret->p_token = NULL;
+ p_interpret->tt_prev = TT_NONE;
+ p_interpret->p_token_prev = NULL;
+ p_interpret->p_token_temp = NULL;
+ p_interpret->ct = CONTROL_NONE;
+
+ return (p_interpret);
+}
+
+void
+interpret_delete(Interpret *p_interpret) {
+ if (!p_interpret)
+ return;
+
+ if (p_interpret->b_scope_delete)
+ scope_delete(p_interpret->p_scope);
+
+ stack_delete(p_interpret->p_stack);
+ free(p_interpret);
+}
+
+void
+_print_lookahead(Interpret *p_interpret) {
+ ListIterator *p_iter = p_interpret->p_iter;
+ ListIteratorState *p_state = listiterator_get_state(p_iter);
+
+ printf("LOOLAHEAD:\n");
+
+ token_print(p_interpret->p_token);
+ printf("\n");
+
+ while (listiterator_has_next(p_iter)) {
+ Token *p_token = listiterator_next(p_iter);
+ token_print(p_token);
+ printf("\n");
+ }
+
+ listiterator_set_state(p_iter, p_state);
+ listiteratorstate_delete(p_state);
+}
+
+int
+_next(Interpret *p_interpret) {
+ if (listiterator_has_next(p_interpret->p_iter)) {
+ p_interpret->p_token_prev = p_interpret->p_token;
+ p_interpret->tt_prev = p_interpret->tt;
+
+ p_interpret->p_token = listiterator_next(p_interpret->p_iter);
+ p_interpret->tt = token_get_tt(p_interpret->p_token);
+ return (1);
+ }
+
+ p_interpret->p_token = NULL;
+ p_interpret->tt = TT_NONE;
+
+ return (0);
+}
+
+TokenType
+_next_tt(Interpret *p_interpret) {
+ if (listiterator_has_next(p_interpret->p_iter)) {
+ Token *p_token = listiterator_current(p_interpret->p_iter);
+ return (token_get_tt(p_token));
+ }
+
+ return (TT_NONE);
+}
+
+int
+_program(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ while (_statement(p_interpret) == 1)
+ garbage_collect();
+
+ return (1);
+}
+
+int
+_var_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_MY) {
+ if (_NEXT_TT != TT_IDENT)
+ _INTERPRET_ERROR("'my' expects identifier", p_interpret->p_token);
+
+ _NEXT
+
+ Token *p_token_ident = p_interpret->p_token;
+
+ _var_assign(p_interpret);
+ _var_list(p_interpret);
+
+ if (p_interpret->tt == TT_SEMICOLON) {
+ _NEXT
+ return (1);
+
+ } else if (p_interpret->p_token != NULL) {
+ _INTERPRET_ERROR("Expected ';'", p_interpret->p_token);
+
+ } else {
+ _INTERPRET_ERROR("Expected ';' after", p_token_ident);
+ }
+ }
+
+ return (0);
+}
+
+int
+_var_assign(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_IDENT) {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ char *c_name = token_get_val(p_token);
+ if (scope_exists(p_interpret->p_scope, c_name)) {
+ _INTERPRET_ERROR("Symbol already defined", p_token);
+ }
+
+ if (p_interpret->tt == TT_ASSIGN) {
+ _NEXT
+
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ if (_expression_(p_interpret)) {
+ function_process_buildin(p_interpret, p_token, p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ p_token = stack_top(p_interpret->p_stack);
+ Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+
+ } else {
+ return (0);
+ }
+
+ } else {
+ Token *p_token = token_new_integer(0);
+ Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+ }
+ }
+
+ return (1);
+}
+
+int
+_var_list(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_COMMA) {
+ _NEXT
+ _var_assign(p_interpret);
+ _var_list(p_interpret);
+ }
+
+ return (1);
+}
+
+int
+_block_get(Interpret *p_interpret, List *p_list_block) {
+ if (p_interpret->tt != TT_PARANT_CL)
+ _INTERPRET_ERROR("Expected '{'", p_interpret->p_token);
+ _NEXT
+
+ int i_num_parant = 0;
+
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ ++i_num_parant;
+
+ } else if (p_interpret->tt == TT_PARANT_CR) {
+ if (--i_num_parant == -1) {
+ _NEXT
+ break; /* for */
+ }
+ }
+
+ list_add_back(p_list_block, p_interpret->p_token);
+
+ _NEXT
+ }
+
+#ifdef DEBUG_BLOCK_GET
+ printf("====> BLOCK\n");
+ list_iterate(p_list_block, token_print_cb);
+ printf("<==== BLOCK\n");
+#endif /* DEBUG_BLOCK_GET */
+
+ return (1);
+}
+
+int
+_expression_get(Interpret *p_interpret, List *p_list_expression) {
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ break; /* for */
+ }
+
+ list_add_back(p_list_expression, p_interpret->p_token);
+
+ _NEXT
+ }
+
+#ifdef DEBUG_EXPRESSION_GET
+ printf("====> EXPRESSION\n");
+ list_iterate(p_list_expression, token_print_cb);
+ printf("<==== EXPRESSION\n");
+#endif /* DEBUG_EXPRESSION_GET */
+
+ return (1);
+}
+
+int
+_block_skip(Interpret *p_interpret) {
+ if (p_interpret->tt != TT_PARANT_CL)
+ _INTERPRET_ERROR("Expected '{'", p_interpret->p_token);
+ _NEXT
+
+ int i_num_parant = 0;
+
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ ++i_num_parant;
+
+ } else if (p_interpret->tt == TT_PARANT_CR) {
+ if (--i_num_parant == -1) {
+ _NEXT
+ break; /* for */
+ }
+ }
+
+ _NEXT
+ }
+
+ return (1);
+}
+
+int
+_proc_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_PROC) {
+ _NEXT
+
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ Token *p_token_ident = p_interpret->p_token;
+ _NEXT
+
+ if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) {
+ _INTERPRET_ERROR("Symbol already defined", p_token_ident);
+ }
+
+ List *p_list_proc = list_new();
+
+ if (_block_get(p_interpret, p_list_proc)) {
+
+ Symbol *p_symbol = symbol_new(SYM_PROCEDURE, p_list_proc);
+ scope_newset(p_interpret->p_scope, token_get_val(p_token_ident),
+ p_symbol);
+
+ return (1);
+ }
+
+ list_delete(p_list_proc);
+ }
+
+ return (0);
+}
+
+int
+_func_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_FUNC) {
+ _NEXT
+
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ Token *p_token_ident = p_interpret->p_token;
+ _NEXT
+
+ if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) {
+ _INTERPRET_ERROR("Symbol already defined", p_token_ident);
+ }
+
+ List *p_list_proc = list_new();
+
+ if (_block_get(p_interpret, p_list_proc)) {
+
+ Symbol *p_symbol = symbol_new(SYM_FUNCTION, p_list_proc);
+ scope_newset(p_interpret->p_scope, token_get_val(p_token_ident),
+ p_symbol);
+
+ return (1);
+ }
+
+ list_delete(p_list_proc);
+ }
+
+ return (0);
+}
+
+int
+_statement(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ for (int i = 0; i < 2; ++i) {
+ if (_proc_decl(p_interpret)) return (1);
+ if (_func_decl(p_interpret)) return (1);
+ if (_var_decl(p_interpret)) return (1);
+ if (_control(p_interpret)) return (1);
+ if (_expression(p_interpret)) return (1);
+ if (_block(p_interpret)) return (1);
+ }
+
+ return (0);
+}
+
+int
+_block(Interpret *p_interpret) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ List *p_list_block = list_new();
+
+ if (_block_get(p_interpret, p_list_block)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ list_delete(p_list_block);
+ return (1);
+ }
+
+ list_delete(p_list_block);
+ }
+
+ return (0);
+}
+
+int
+_expression(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_expression_(p_interpret)) {
+ if (p_interpret->tt == TT_SEMICOLON) {
+ _NEXT
+
+ } else {
+ _INTERPRET_ERROR("Expected ';'", p_interpret->p_token);
+ }
+
+ stack_clear(p_interpret->p_stack);
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_expression_(Interpret *p_interpret) {
+ return (_compare(p_interpret));
+}
+
+int
+_control(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ Token *p_token = p_interpret->p_token;
+
+ switch (p_interpret->tt) {
+ case TT_IF:
+ case TT_IFNOT:
+ {
+ TokenType tt = p_interpret->tt;
+ _NEXT
+ if (_expression_(p_interpret)) {
+ Token *p_token_top = stack_pop(p_interpret->p_stack);
+ List *p_list_block = list_new();
+ _block_get(p_interpret, p_list_block);
+ int ret = 0;
+
+ switch (tt) {
+ case TT_IF:
+ if (convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ ret = interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ }
+ break;
+ case TT_IFNOT:
+ if (!convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ ret = interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ }
+ break;
+ NO_DEFAULT;
+ }
+
+ list_delete(p_list_block);
+ return (1);
+
+ } else {
+ _INTERPRET_ERROR("Expected expression after control keyword", p_token);
+ }
+ }
+ break;
+ case TT_WHILE:
+ case TT_UNTIL:
+ {
+ TokenType tt = p_interpret->tt;
+ List *p_list_expr = list_new(), *p_list_block = list_new();
+ _Bool b_flag = true;
+
+ _NEXT
+
+ _expression_get(p_interpret, p_list_expr);
+ _block_get(p_interpret, p_list_block);
+ Token *p_token_backup = p_interpret->p_token;
+
+ do {
+ Stack *p_stack_backup = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ ListIterator *p_iter_backup = p_interpret->p_iter;
+ p_interpret->p_iter = listiterator_new(p_list_expr);
+
+ _NEXT
+
+ /* Dont use if here, because we want to check the p_itnerpret->ct */
+ if (_expression_(p_interpret)) {
+ Token *p_token_top = stack_pop(p_interpret->p_stack);
+
+ if (p_token_top == NULL) {
+ printf("FOO\n");
+ exit(0);
+ }
+ if (tt == TT_WHILE) {
+ if (convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+
+ } else {
+ b_flag = false;
+ }
+
+ } else if (tt == TT_UNTIL) {
+ if (!convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+
+ } else {
+ b_flag = false;
+ }
+ }
+
+ /*
+ switch (p_interpret->ct) {
+ case CONTROL_BREAK:
+ p_interpret->ct = CONTROL_NONE;
+ b_flag = false;
+ break;
+ case CONTROL_NEXT:
+ p_interpret->ct = CONTROL_NONE;
+ break;
+ NO_DEFAULT;
+ }
+ */
+
+ } else {
+ _INTERPRET_ERROR("Expected expression after control keyword", p_token);
+ }
+
+ listiterator_delete(p_interpret->p_iter);
+ p_interpret->p_iter = p_iter_backup;
+
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack_backup;
+
+ } while (b_flag);
+
+ list_delete(p_list_expr);
+ list_delete(p_list_block);
+ p_interpret->p_token = p_token_backup;
+ p_interpret->tt = token_get_tt(p_token_backup);
+
+ return (1);
+ }
+ break;
+ NO_DEFAULT;
+ }
+
+ return (0);
+}
+
+int
+_compare(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_sum(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_EQ:
+ case TT_NEQ:
+ case TT_LT:
+ case TT_GT:
+ case TT_LE:
+ case TT_GE:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_sum(p_interpret))
+ _INTERPRET_ERROR("Expected sum", p_interpret->p_token);
+
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_sum(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_product(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_ADD:
+ case TT_SUB:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_product(p_interpret))
+ _INTERPRET_ERROR("Expected product", p_token);
+
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_product(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_product2(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_MULT:
+ case TT_DIV:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_product2(p_interpret))
+ _INTERPRET_ERROR("Expected product2", p_token);
+
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_product2(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_term(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_ASSIGN:
+ {
+ Token *p_token = p_interpret->p_token;
+ Token *p_token_temp = p_interpret->p_token_prev;
+ _NEXT
+
+ if (!_expression_(p_interpret))
+ _INTERPRET_ERROR("Expected expression", p_token);
+
+ p_interpret->p_token_temp = p_token_temp;
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+ p_interpret->p_token_temp = NULL;
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_term(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ switch (p_interpret->tt) {
+ case TT_INTEGER:
+ case TT_DOUBLE:
+ case TT_STRING:
+ stack_push(p_interpret->p_stack, p_interpret->p_token);
+ _NEXT
+ return (1);
+
+ case TT_IDENT:
+ {
+ if (_NEXT_TT != TT_ASSIGN) {
+ if (function_is_buildin(p_interpret->p_token)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ if (_HAS_NEXT) {
+ _NEXT
+ if (_expression_(p_interpret));
+
+ } else {
+ _SKIP
+ }
+
+ function_process_buildin(p_interpret, p_token, p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+
+ } else if (function_is_self_defined(p_interpret)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ _NEXT
+ if (_expression_(p_interpret));
+
+ function_process_self_defined(p_interpret, p_token);
+
+ if (stack_empty(p_interpret->p_stack)) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, 0);
+ stack_push(p_interpret->p_stack, p_token);
+ }
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+ }
+ }
+
+ /* It is not a function, it is a variable or some sort of */
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
+
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
+
+ SymbolType st = symbol_get_sym(p_symbol);
+
+ switch (st) {
+ case SYM_VARIABLE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ /* Example: proc foo { foo = "Hello"; } foo; say foo; */
+ case SYM_PROCEDURE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ NO_DEFAULT;
+ }
+ }
+ break;
+ case TT_DEFINED:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'defined'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Token *p_token = token_new_integer(0);
+
+ if (scope_exists(p_interpret->p_scope, c_name))
+ token_set_ival(p_token, 1);
+
+ stack_push(p_interpret->p_stack, p_token);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_UNDEF:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'defined'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Token *p_token = NULL;
+ Symbol *p_symbol = NULL;
+
+ if ((p_symbol = scope_remove(p_interpret->p_scope, c_name))) {
+ symbol_delete(p_symbol);
+ p_token = token_new_integer(1);
+
+ } else {
+ p_token = token_new_integer(0);
+ }
+
+ stack_push(p_interpret->p_stack, p_token);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_PARANT_L:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (_expression_(p_interpret)) {
+ if (p_interpret->tt != TT_PARANT_R)
+ _INTERPRET_ERROR("Expected ')'", p_token);
+
+ } else {
+ _INTERPRET_ERROR("Expected expression", p_token);
+ }
+ }
+ _NEXT
+ return (1);
+
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+int
+interpret_process(Interpret *p_interpret) {
+ p_interpret->p_iter = listiterator_new(p_interpret->p_list_token);
+
+ _NEXT
+ _program(p_interpret);
+
+ listiterator_delete(p_interpret->p_iter);
+
+ return (1);
+}
+
+
+int
+interpret_subprocess(Interpret *p_interpret, List *p_list_token) {
+ Interpret *p_interpret_sub = interpret_new(p_list_token,
+ NULL);
+
+ p_interpret_sub->p_scope = p_interpret->p_scope;
+
+ int i_ret = interpret_process(p_interpret_sub);
+ p_interpret->ct = p_interpret_sub->ct;
+
+ interpret_delete(p_interpret_sub);
+
+ return (i_ret);
+}
+
+void
+interpret_run(Fype *p_fype) {
+ Interpret *p_interpret =
+ interpret_new(p_fype->p_list_token, p_fype->p_hash_syms);
+
+ interpret_process(p_interpret);
+
+ interpret_delete(p_interpret);
+}
+
diff --git a/src/core/interpret.h b/src/core/interpret.h
new file mode 100644
index 0000000..e2f4cb7
--- /dev/null
+++ b/src/core/interpret.h
@@ -0,0 +1,75 @@
+/*:*
+ *: File: ./src/core/interpret.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 INTERPRET_H
+#define INTERPRET_H
+
+#include "../data/list.h"
+#include "../data/stack.h"
+#include "../data/hash.h"
+
+#include "../fype.h"
+
+#include "garbage.h"
+#include "scope.h"
+#include "token.h"
+
+typedef enum {
+ CONTROL_NONE,
+ CONTROL_NEXT,
+ CONTROL_BREAK,
+} ControlType;
+
+typedef struct {
+ List *p_list_token;
+ Scope *p_scope;
+ _Bool b_scope_delete;
+ Stack *p_stack;
+ ControlType ct;
+
+ ListIterator *p_iter;
+ Token *p_token;
+ TokenType tt;
+ Token *p_token_prev;
+ TokenType tt_prev;
+ Token *p_token_temp;
+} Interpret;
+
+Interpret* interpret_new(List *p_list_token, Hash *p_hash_syms);
+void interpret_delete(Interpret *p_interpret);
+void interpret_run(Fype *p_type);
+int interpret_process(Interpret *p_interpret);
+int interpret_subprocess(Interpret *p_interpret, List *p_list_token);
+
+#endif /* INTERPRET_H */
diff --git a/src/core/scanner.c b/src/core/scanner.c
new file mode 100644
index 0000000..85f0780
--- /dev/null
+++ b/src/core/scanner.c
@@ -0,0 +1,391 @@
+/*:*
+ *: File: ./src/core/scanner.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "scanner.h"
+
+#include <ctype.h>
+#include <string.h>
+
+const char const *KEYWORDS[] = {
+ "if",
+ "else",
+ "elsif",
+ "while",
+ "ret",
+ "const",
+};
+
+const char const *OPERATORS[] = {
+ "!",
+ "!=",
+ "(",
+ ")",
+ "*",
+ "+",
+ "++",
+ ",",
+ "-",
+ "--",
+ ".",
+ "/",
+ "\\",
+ ":",
+ "==",
+ ";",
+ "<<",
+ "<",
+ "<=",
+ "=",
+ ">=",
+ ">>",
+ ">",
+ "{",
+ "}",
+};
+
+const char TOKENENDS[] = "{}();:,.";
+int CODESTRING_INDEX = 0;
+
+Scanner*
+scanner_new(List *p_list_token, Tupel *p_tupel_argv) {
+ Scanner *p_scanner = malloc(sizeof(Scanner));
+
+ Dat *p_dat_string = p_tupel_argv->a;
+
+ if (dat_empty(p_dat_string))
+ ERROR("No source given");
+
+ if (argv_checkopts("e", p_tupel_argv)) {
+ p_scanner->c_codestring = dat_pop(p_dat_string);
+ p_scanner->c_filename = NULL;
+ p_scanner->fp = NULL;
+
+ } else {
+ p_scanner->c_codestring = NULL;
+ p_scanner->c_filename = dat_pop(p_dat_string);
+ p_scanner->fp = fopen(p_scanner->c_filename, "r");
+
+ if (!p_scanner->fp)
+ ERROR("Could not open '%s' for reading!", p_scanner->c_filename);
+ }
+
+ p_scanner->p_list_token = p_list_token;
+
+ p_scanner->i_current_line_nr = 1;
+ p_scanner->i_current_pos_nr = 0;
+
+ p_scanner->i_num_keywords = sizeof(KEYWORDS) / sizeof(char const *);
+ p_scanner->i_num_operators = sizeof(OPERATORS) / sizeof(char const *);
+ p_scanner->i_num_tokenends = strlen(TOKENENDS);
+
+ return p_scanner;
+}
+
+void
+scanner_delete(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ fclose(p_scanner->fp);
+ free(p_scanner);
+}
+
+void
+scanner_post_task(Scanner *p_scanner) {
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ ListIterator *p_iter = listiterator_new(p_list_token);
+
+ Token *pt_last[] = { NULL, NULL };
+ TokenType tt_last[] = { TT_NONE, TT_NONE };
+
+ while (listiterator_has_next(p_iter)) {
+ ListElem *p_le = listiterator_next_elem(p_iter);
+ Token *p_token = p_le->p_val;
+ TokenType tt_cur = token_get_tt(p_token);
+
+ if (pt_last[0]) {
+ if (tt_cur == TT_INTEGER && tt_last[1] == TT_DOT
+ && tt_last[0] == TT_INTEGER) {
+
+ token_ref_down(pt_last[0]);
+ token_ref_down(pt_last[1]);
+
+ char *c_2 = token_get_val(p_token);
+ char *c_0 = token_get_val(pt_last[0]);
+ int i_len = strlen(c_2) + strlen(c_0) + 1;
+ char *c_new = calloc(i_len+1, sizeof(char));
+
+ sprintf(c_new, "%s.%s", c_0, c_2);
+ free(c_2);
+ c_new[i_len] = 0;
+
+ token_set_val(p_token, c_new);
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, atof(c_new));
+
+ list_remove_elem(p_list_token, p_le->p_prev);
+ list_remove_elem(p_list_token, p_le->p_prev);
+
+ pt_last[0] = pt_last[1] = NULL;
+ tt_last[0] = tt_last[1] = TT_NONE;
+ }
+ }
+
+ tt_last[0] = tt_last[1];
+ tt_last[1] = tt_cur;
+
+ pt_last[0] = pt_last[1];
+ pt_last[1] = p_token;
+ }
+
+ listiterator_delete(p_iter);
+}
+
+_Bool
+_scanner_has_next_char(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ return !feof(p_scanner->fp);
+
+ return p_scanner->c_codestring[CODESTRING_INDEX] != 0;
+}
+
+char
+_scanner_get_next_char(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ return fgetc(p_scanner->fp);
+
+ return (p_scanner->c_codestring[CODESTRING_INDEX++]);
+}
+
+void
+scanner_run(Fype *p_fype) {
+ Scanner *p_scanner = scanner_new(p_fype->p_list_token, p_fype->p_tupel_argv);
+
+ int i_token_len = 0;
+ char *c_token = malloc(sizeof(char));
+
+ c_token[0] = 0;
+
+ while ( _scanner_has_next_char(p_scanner) ) {
+ //char c = fgetc(fp);
+ char c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+
+ switch (c) {
+ case '#':
+ {
+ c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+ _Bool b_multi_comment = c == '*';
+
+ do {
+ c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+ if (c == '\n') {
+ ++p_scanner->i_current_line_nr;
+ p_scanner->i_current_pos_nr = 0;
+
+ if (!b_multi_comment)
+ break;
+
+ } else if (b_multi_comment && c == '*' &&
+ _scanner_has_next_char(p_scanner)) {
+ if ( (c = _scanner_get_next_char(p_scanner)) == '#')
+ break;
+
+ else if (c == '\n')
+ ++p_scanner->i_current_line_nr;
+ }
+
+ } while ( _scanner_has_next_char(p_scanner) );
+ }
+
+ break;
+
+ case '"':
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+ {
+ int i_num_nl = 0;
+ do {
+ // c = fgetc(fp);
+ c = _scanner_get_next_char(p_scanner);
+ if ( c == '\n' ) {
+ ++i_num_nl;
+ p_scanner->i_current_pos_nr = 0;
+
+ i_token_len += 2;
+ c_token = realloc(c_token, sizeof(char) * (i_token_len + 1));
+ c_token[i_token_len-2] = '\\';
+ c_token[i_token_len-1] = 'n';
+ c_token[i_token_len] = 0;
+
+ } else if (c == '"') {
+ if (i_token_len && c_token[i_token_len-1] == '\\')
+ c_token[i_token_len-1] = '"';
+
+ else
+ break;
+
+ } else {
+ ++i_token_len;
+ c_token = realloc(c_token, sizeof(char) * (i_token_len + 1));
+ c_token[i_token_len-1] = c;
+ c_token[i_token_len] = 0;
+ }
+
+ //} while ( !feof(fp) );
+ } while ( _scanner_has_next_char(p_scanner) );
+
+ scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING);
+
+ if (i_num_nl)
+ p_scanner->i_current_line_nr += i_num_nl;
+ }
+
+ break;
+
+ case '\n':
+ case '\t':
+ case ' ':
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+
+ if (c == '\n') {
+ ++p_scanner->i_current_line_nr;
+ p_scanner->i_current_pos_nr = 0;
+ }
+
+ break;
+
+ default:
+ if (i_token_len) {
+ char d = c_token[i_token_len-1];
+ if ((!isalpha(d) && !isdigit(d) /*&& d != '-'*/) &&
+ (isalpha(c) || isdigit(c))) {
+
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+
+ } else {
+ for (int i = 0; i < p_scanner->i_num_tokenends; ++i) {
+ if (TOKENENDS[i] == c) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ break;
+ }
+ }
+ }
+ }
+
+ ++i_token_len;
+ c_token = realloc(c_token, sizeof(char) * i_token_len + 1);
+ c_token[i_token_len-1] = c;
+ c_token[i_token_len] = 0;
+ }
+ }
+
+ if (argv_checkopts("e", p_fype->p_tupel_argv) && i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+
+ scanner_post_task(p_scanner);
+
+ char *c_filename = scanner_get_filename(p_scanner);
+ scanner_delete(p_scanner);
+
+ if (argv_checkopts("TV", p_fype->p_tupel_argv))
+ list_iterate(p_fype->p_list_token, token_print_cb);
+
+ char *c_basename = NULL;
+ if (c_filename) {
+ int i_len = strlen(c_filename) - 3;
+ c_basename = calloc(i_len+1, sizeof(char));
+ strncpy(c_basename, c_filename, i_len);
+ c_basename[i_len] = 0;
+
+ } else {
+ char *c_basename = calloc(1, sizeof(char));
+ c_basename[0] = 0;
+ }
+
+ p_fype->c_basename = c_basename;
+
+ /*
+ c_token = calloc(2, sizeof(char*));
+ c_token[0] = ';';
+ c_token[1] = '\0';
+ i_token_len = 1;
+
+ scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING);
+ */
+}
+
+void
+scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len,
+ TokenType tt_cur) {
+
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ Token *p_token = token_new(*cc_token, tt_cur, p_scanner->i_current_line_nr,
+ p_scanner->i_current_pos_nr, p_scanner->c_filename);
+
+ list_add_back(p_list_token, p_token);
+ token_ref_up(p_token);
+
+ *cc_token = malloc(sizeof(char));
+ (*cc_token)[0] = 0;
+ *p_token_len = 0;
+}
+
+TokenType
+scanner_get_tt_cur(char *c_token) {
+ if (isdigit(c_token[0]))
+ return TT_INTEGER;
+
+ if (c_token[0] == '-' && 1 < strlen(c_token) && isdigit(c_token[1]))
+ return TT_INTEGER;
+
+ TokenType tt_cur = get_tt(c_token);
+
+ return tt_cur == TT_NONE ? TT_IDENT : tt_cur;
+}
+
+void
+scanner_cleanup_list_token_cb(void *p_void) {
+ Token *p_token = p_void;
+ token_delete(p_token);
+}
diff --git a/src/core/scanner.h b/src/core/scanner.h
new file mode 100644
index 0000000..fc07a28
--- /dev/null
+++ b/src/core/scanner.h
@@ -0,0 +1,71 @@
+/*:*
+ *: File: ./src/core/scanner.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 SCANNER_H
+#define SCANNER_H
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "token.h"
+#include "../fype.h"
+#include "../data/dat.h"
+
+#define scanner_get_list_token(s) s->p_list_token
+#define scanner_get_fp(s) s->fp
+#define scanner_get_filename(s) s->c_filename
+#define scanner_get_codestring(s) s->c_codestring
+
+typedef struct {
+ int i_current_line_nr;
+ int i_current_pos_nr;
+ int i_num_keywords;
+ int i_num_operators;
+ int i_num_tokenends;
+ char *c_filename;
+ char *c_codestring;
+ FILE *fp;
+ List *p_list_token;
+} Scanner;
+
+Scanner *scanner_new(List *p_list_token, Tupel *p_tupel_argv);
+void scanner_post_task(Scanner *p_scanner);
+void scanner_delete(Scanner *p_scanner);
+void scanner_run(Fype *p_fype);
+void scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len,
+ TokenType tt_cur);
+TokenType scanner_get_tt_cur(char *c_token);
+void scanner_cleanup_list_token_cb(void *p_void);
+
+#endif
diff --git a/src/core/scope.c b/src/core/scope.c
new file mode 100644
index 0000000..f1ca006
--- /dev/null
+++ b/src/core/scope.c
@@ -0,0 +1,150 @@
+/*:*
+ *: File: ./src/core/scope.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "garbage.h"
+#include "scope.h"
+#include "symbol.h"
+
+Scope*
+scope_new(Hash *p_hash_syms) {
+ Scope *p_scope = malloc(sizeof(Scope));
+
+ p_scope->p_hash_global = p_hash_syms;
+ p_scope->p_stack_scopes = stack_new();
+
+ return (p_scope);
+}
+
+void
+scope_delete(Scope *p_scope) {
+ while (!stack_empty(p_scope->p_stack_scopes))
+ scope_down(p_scope);
+
+ stack_delete(p_scope->p_stack_scopes);
+
+ free(p_scope);
+}
+
+void
+scope_up(Scope *p_scope) {
+ stack_push(p_scope->p_stack_scopes, hash_new(1024));
+}
+
+void
+scope_down(Scope *p_scope) {
+ Hash *p_hash_syms = stack_pop(p_scope->p_stack_scopes);
+ hash_iterate(p_hash_syms, symbol_cleanup_hash_syms_cb);
+ hash_delete(p_hash_syms);
+}
+
+static Hash*
+_scope_get_hash(Scope *p_scope, char *c_key) {
+ StackIterator *p_iter = stackiterator_new(p_scope->p_stack_scopes);
+
+ while (stackiterator_has_next(p_iter)) {
+ Hash *p_hash_syms = stackiterator_next(p_iter);
+ Symbol *p_symbol = hash_get(p_hash_syms, c_key);
+
+ if (p_symbol != NULL) {
+ stackiterator_delete(p_iter);
+ return (p_hash_syms);
+ }
+ }
+
+ stackiterator_delete(p_iter);
+
+ if (hash_get(p_scope->p_hash_global, c_key))
+ return (p_scope->p_hash_global);
+
+ return (NULL);
+}
+
+Symbol*
+scope_get(Scope *p_scope, char *c_key) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (NULL);
+
+ return (hash_get(p_hash_syms, c_key));
+}
+
+Symbol*
+scope_remove(Scope *p_scope, char *c_key) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (NULL);
+
+ Symbol *p_symbol = hash_remove(p_hash_syms, c_key);
+
+ return (p_symbol);
+}
+
+_Bool
+scope_exists(Scope *p_scope, char *c_key) {
+ return (scope_get(p_scope, c_key) != NULL);
+}
+
+_Bool
+scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (false);
+
+ hash_remove(p_hash_syms, c_key);
+ hash_insert(p_hash_syms, c_key, p_symbol);
+
+ return (true);
+}
+
+_Bool
+scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol) {
+ Hash *p_hash_syms = NULL;
+
+ if (stack_empty(p_scope->p_stack_scopes)) {
+ if (hash_get(p_scope->p_hash_global, c_key) != NULL)
+ return (false);
+
+ p_hash_syms = p_scope->p_hash_global;
+
+ } else {
+ p_hash_syms = stack_top(p_scope->p_stack_scopes);
+ }
+
+ hash_insert(p_hash_syms, c_key, p_symbol);
+
+ return (true);
+}
diff --git a/src/core/scope.h b/src/core/scope.h
new file mode 100644
index 0000000..63a4373
--- /dev/null
+++ b/src/core/scope.h
@@ -0,0 +1,59 @@
+/*:*
+ *: File: ./src/core/scope.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 SCOPE_H
+#define SCOPE_H
+
+#include "../data/hash.h"
+#include "../data/stack.h"
+#include "../defines.h"
+#include "symbol.h"
+
+
+typedef struct {
+ Hash *p_hash_global;
+ Stack *p_stack_scopes;
+} Scope;
+
+Scope* scope_new(Hash *p_hash_syms);
+void scope_delete(Scope *p_scope);
+Symbol *scope_get(Scope *p_scope, char *c_key);
+Symbol *scope_remove(Scope *p_scope, char *c_key);
+_Bool scope_exists(Scope *p_scope, char *c_key);
+_Bool scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol);
+_Bool scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol);
+void scope_down(Scope *p_scope);
+void scope_up(Scope *p_scope);
+
+#endif /* SCOPE_H */
diff --git a/src/core/symbol.c b/src/core/symbol.c
new file mode 100644
index 0000000..721603a
--- /dev/null
+++ b/src/core/symbol.c
@@ -0,0 +1,66 @@
+/*:*
+ *: File: ./src/core/symbol.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "symbol.h"
+
+#include "../data/list.h"
+
+Symbol*
+symbol_new(SymbolType sym, void *p_val) {
+ Symbol *p_symbol = malloc(sizeof(Symbol));
+
+ p_symbol->sym = sym;
+ p_symbol->p_val = p_val;
+
+ return p_symbol;
+}
+
+void
+symbol_delete(Symbol *p_symbol) {
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ list_delete(p_list_token);
+ }
+ break;
+ NO_DEFAULT;
+ }
+ free(p_symbol);
+}
+
+void
+symbol_cleanup_hash_syms_cb(void *p_void) {
+ symbol_delete(p_void);
+}
diff --git a/src/core/symbol.h b/src/core/symbol.h
new file mode 100644
index 0000000..5744383
--- /dev/null
+++ b/src/core/symbol.h
@@ -0,0 +1,64 @@
+/*:*
+ *: File: ./src/core/symbol.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 "../defines.h"
+
+#define symbol_set_val(s,v) s->p_val = v
+#define symbol_set_sym(s,st) s->sym = st
+#define symbol_get_val(s) s->p_val
+#define symbol_get_sym(s) s->sym
+#define IS_A_FUNCTION(s) (s == SYM_INLINEFUNCTION || s == SYM_FUNCTION)
+#define IS_NOT_A_FUNCTION(s) !IS_A_FUNCTION(s)
+
+typedef enum {
+ SYM_CONSTANT,
+ SYM_VARIABLE,
+ SYM_BUILDIN,
+ SYM_PROCEDURE,
+ SYM_FUNCTION,
+} SymbolType;
+
+typedef struct {
+ SymbolType sym;
+ void *p_val;
+} Symbol;
+
+Symbol* symbol_new(SymbolType sym, void *p_val);
+void symbol_delete(Symbol *p_symbol);
+void symbol_cleanup_hash_syms_cb(void *p_void);
+
+#endif
diff --git a/src/core/token.c b/src/core/token.c
new file mode 100644
index 0000000..1573371
--- /dev/null
+++ b/src/core/token.c
@@ -0,0 +1,380 @@
+/*:*
+ *: File: ./src/core/token.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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.
+ *:*/
+
+#include "token.h"
+
+#include "garbage.h"
+
+#define CHECK(...) if (!strcmp(c_token, __VA_ARGS__)) return
+
+long TOKEN_ID_COUNTER = 0;
+
+TokenType
+get_tt(char *c_token) {
+ CHECK("if") TT_IF;
+ CHECK("ifnot") TT_IFNOT;
+ CHECK("else") TT_ELSE;
+ CHECK("break") TT_BREAK;
+ CHECK("while") TT_WHILE;
+ CHECK("until") TT_UNTIL;
+ CHECK("int") TT_INT;
+ CHECK("next") TT_NEXT;
+ CHECK("defined") TT_DEFINED;
+ CHECK("undef") TT_UNDEF;
+ CHECK("ret") TT_RET;
+ CHECK("const") TT_CONST;
+ CHECK("proc") TT_PROC;
+ CHECK("func") TT_FUNC;
+ CHECK("my") TT_MY;
+ CHECK("not") TT_NOT;
+ CHECK("!=") TT_NEQ;
+ CHECK("=~") TT_RE;
+ CHECK("(") TT_PARANT_L;
+ CHECK(")") TT_PARANT_R;
+ CHECK("*") TT_MULT;
+ CHECK("+") TT_ADD;
+ CHECK("++") TT_INCR;
+ CHECK(",") TT_COMMA;
+ CHECK("-") TT_SUB;
+ CHECK("--") TT_DECR;
+ CHECK(".") TT_DOT;
+ CHECK("/") TT_DIV;
+ CHECK("\\") TT_VID;
+ CHECK(":") TT_DDOT;
+ CHECK("==") TT_EQ;
+ CHECK(";") TT_SEMICOLON;
+ CHECK("<<") TT_LSHIFT;
+ CHECK(">>") TT_RSHIFT;
+ CHECK("and") TT_AND;
+ CHECK("or") TT_OR;
+ CHECK("xor") TT_XOR;
+ CHECK("=") TT_ASSIGN;
+ CHECK("<") TT_LT;
+ CHECK(">") TT_GT;
+ CHECK(">=") TT_GE;
+ CHECK("<=") TT_LE;
+ CHECK("{") TT_PARANT_CL;
+ CHECK("}") TT_PARANT_CR;
+
+ return TT_NONE;
+}
+
+#define CASE(t,r) case t: return r;
+
+char*
+tt_get_name(TokenType tt_cur) {
+ switch (tt_cur) {
+ CASE(START_TERMINALS, "START_TERMINALS")
+ CASE(START_TYPES, "START_TYPES")
+ CASE(START_NUMERICAL, "START_NUMERICAL")
+ CASE(START_ASSIGNABLES, "START_ASSIGNABLES")
+ CASE(TT_IDENT, "TT_IDENT")
+ CASE(TT_DOUBLE,"TT_DOUBLE")
+ CASE(TT_STRING,"TT_STRING")
+ CASE(TT_INTEGER,"TT_INTEGER")
+ CASE(TT_BOOL,"TT_BOOL")
+ CASE(END_ASSIGNABLES, "END_ASSIGNABLES")
+ CASE(END_NUMERICAL, "END_NUMERICAL")
+ CASE(END_TYPES, "END_TYPES")
+
+ // Keywords
+ CASE(START_KEYWORDS, "START_KEYWORDS")
+ CASE(TT_ELSE,"TT_ELSE")
+ CASE(TT_BREAK,"TT_BREAK")
+ CASE(TT_IF,"TT_IF")
+ CASE(TT_IFNOT,"TT_IFNOT")
+ CASE(TT_RET,"TT_RET")
+ CASE(TT_CONST,"TT_CONST")
+ CASE(TT_PROC,"TT_PROC")
+ CASE(TT_FUNC,"TT_FUNC")
+ CASE(TT_MY,"TT_MY")
+ CASE(TT_WHILE,"TT_WHILE")
+ CASE(TT_UNTIL,"TT_UNTIL")
+ CASE(TT_NEXT,"TT_NEXT")
+ CASE(TT_DEFINED,"TT_DEFINED")
+ CASE(TT_UNDEF,"TT_UNDEF")
+ CASE(TT_INT,"TT_INT")
+ CASE(END_KEYWORDS, "END_KEYWORDS")
+
+ // Braces
+ CASE(START_PARANTS, "START_PARANTS")
+ CASE(TT_PARANT_CL,"TT_PARANT_CL")
+ CASE(TT_PARANT_CR,"TT_PARANT_CR")
+ CASE(TT_PARANT_L,"TT_PARANT_L")
+ CASE(TT_PARANT_R,"TT_PARANT_R")
+ CASE(END_PARANTS, "END_PARANTS")
+
+ // Operators
+ CASE(START_OPERATORS, "START_OPERATORS")
+ CASE(TT_ADD,"TT_ADD")
+ CASE(TT_ASSIGN,"TT_ASSIGN")
+ CASE(TT_COMMA,"TT_COMMA")
+ CASE(TT_DDOT,"TT_DDOT")
+ CASE(TT_DECR,"TT_DECR")
+ CASE(TT_DIV,"TT_DIV")
+ CASE(TT_VID,"TT_VID")
+ CASE(TT_DOT,"TT_DOT")
+ CASE(TT_EQ,"TT_EQ")
+ CASE(TT_LE,"TT_LE")
+ CASE(TT_LT,"TT_LT")
+ CASE(TT_GE,"TT_GE")
+ CASE(TT_GT,"TT_GT")
+ CASE(TT_INCR,"TT_INCR")
+ CASE(TT_LSHIFT,"TT_LSHIFT")
+ CASE(TT_RSHIFT,"TT_RSHIFT")
+ CASE(TT_AND,"TT_AND")
+ CASE(TT_OR,"TT_OR")
+ CASE(TT_XOR,"TT_XOR")
+ CASE(TT_NOT,"TT_NOT")
+ CASE(TT_MULT,"TT_MULT")
+ CASE(TT_NEQ,"TT_NEQ")
+ CASE(TT_RE,"TT_RE")
+ CASE(TT_NOTEQ,"TT_NOTEQ")
+ CASE(TT_SEMICOLON,"TT_SEMICOLON")
+ CASE(TT_SUB,"TT_SUB")
+ CASE(END_OPERATORS, "END_OPERATORS")
+ CASE(END_TERMINALS, "END_TERMINALS")
+
+ // Diverse
+ CASE(TT_NONE,"TT_NONE")
+ CASE(TT_END_OF_CODE,"TT_END_OF_CODE")
+ }
+
+ // Never reach this point
+ return "XXXXXXX";
+}
+
+Token*
+token_new(char *c_val, TokenType tt_cur, int i_line_nr, int i_pos_nr, char *c_filename) {
+ Token *p_token = token_new_dummy();
+
+ p_token->c_val = c_val;
+ p_token->i_val = 0;
+ p_token->d_val = 0;
+ p_token->tt_cur = tt_cur;
+ p_token->i_line_nr = i_line_nr;
+ p_token->i_pos_nr = i_pos_nr;
+ p_token->c_filename = c_filename;
+
+ switch (tt_cur) {
+ case TT_INTEGER:
+ p_token->i_val = atoi(c_val);
+ break;
+ case TT_DOUBLE:
+ {
+ p_token->d_val = atof(c_val);
+ break;
+ }
+ NO_DEFAULT;
+ }
+
+ return p_token;
+}
+
+Token*
+token_new_integer(int i_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, i_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_double(double d_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, d_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_string(char *c_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_STRING);
+
+ p_token->c_val = calloc(strlen(c_val)+1, sizeof(char));
+ strcpy(p_token->c_val, c_val);
+
+ return (p_token);
+}
+
+
+Token*
+token_new_(char *c_val, TokenType tt_cur, char *c_filename) {
+ return token_new(c_val, tt_cur, -1, -1, c_filename);
+}
+
+Token*
+token_new_dummy() {
+ Token *p_token = malloc(sizeof(Token));
+
+ p_token->c_val = NULL;
+ p_token->tt_cur = TT_NONE;
+ p_token->i_line_nr = -1;
+ p_token->i_pos_nr = -1;
+ p_token->c_filename = NULL;
+ p_token->u_token_id = TOKEN_ID_COUNTER++;
+ p_token->i_ref_count = 0;
+
+ /* Register the token in the garbage collector */
+ garbage_add_token(p_token);
+
+ return p_token;
+}
+
+Token*
+token_new_copy(Token *p_token) {
+ Token *p_token_copy = malloc(sizeof(Token));
+ p_token->u_token_id = TOKEN_ID_COUNTER++;
+
+ if (p_token_copy == NULL)
+ ERROR("Memory alloc error");
+
+ token_copy_vals(p_token_copy, p_token);
+ p_token_copy->i_ref_count = 0;
+
+ /* Register the token in the garbage collector */
+ garbage_add_token(p_token_copy);
+
+ return (p_token_copy);
+}
+
+void token_copy_vals(Token *p_token_to, Token *p_token_from) {
+ int i_len;
+
+ // TODO: Check against mem leak
+ // if (p_token_to->c_val)
+ // free(p_token_to->c_val);
+
+ if (p_token_from->c_val) {
+ i_len = strlen(p_token_from->c_val);
+ p_token_to->c_val = calloc(i_len+1, sizeof(char));
+ strcpy(p_token_to->c_val, p_token_from->c_val);
+ } else {
+ p_token_to->c_val = NULL;
+ }
+
+ p_token_to->tt_cur = p_token_from->tt_cur;
+ p_token_to->i_val = p_token_from->i_val;
+ p_token_to->d_val = p_token_from->d_val;
+ p_token_to->i_line_nr = p_token_from->i_line_nr;
+ p_token_to->i_pos_nr = p_token_from->i_pos_nr;
+ p_token_to->c_filename = p_token_from->c_filename;
+}
+
+void
+token_delete_cb(void *p_void) {
+ token_delete(p_void);
+}
+
+void
+token_ref_down_cb(void *p_void) {
+ Token *p_token = p_void;
+ token_ref_down(p_token);
+}
+
+void*
+token_copy_cb(void *p_void) {
+ return (token_new_copy(p_void));
+}
+
+void
+token_delete(Token *p_token) {
+ if (token_ref_down(p_token) <= 0) {
+ if (p_token->i_ref_count == 0) {
+#ifdef DEBUG_TOKEN_REFCOUNT
+ printf("Token refcount debug: Token ref count is 0 == %d\n",
+ p_token->i_ref_count);
+#endif /* DEBUG_TOKEN_REFCOUNT */
+ if (p_token->c_val)
+ free(p_token->c_val);
+
+ free(p_token);
+ }
+#ifdef DEBUG_TOKEN_REFCOUNT
+ else {
+ printf("Token refcount debug: Token ref count is 0 > %d\n",
+ p_token->i_ref_count);
+ }
+#endif /* DEBUG_TOKEN_REFCOUNT */
+ }
+#ifdef DEBUG_TOKEN_REFCOUNT
+ else {
+ printf("Token refcount debug: Token ref count is 0 < %d\n",
+ p_token->i_ref_count);
+ }
+#endif /* DEBUG_TOKEN_REFCOUNT */
+}
+
+void
+token_print(Token *p_token) {
+ printf("(id=%05u, line=%05d, pos=%04d, type=%s, val=%s, ival=%d, dval=%f,"
+ " refs=%d)",
+ p_token->u_token_id,
+ p_token->i_line_nr,
+ p_token->i_pos_nr,
+ tt_get_name(p_token->tt_cur),
+ p_token->c_val,
+ p_token->i_val,
+ p_token->d_val,
+ p_token->i_ref_count);
+}
+
+void
+token_print_val(Token *p_token) {
+ TokenType tt = token_get_tt(p_token);
+ switch (tt) {
+ case TT_INTEGER:
+ printf("(%s, %d)", tt_get_name(tt), token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("(%s, %f)", tt_get_name(tt), token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("(%s, %s)", tt_get_name(tt), token_get_val(p_token));
+ break;
+ default:
+ ERROR("Ouups(%s)!", tt_get_name(tt));
+ }
+}
+
+void
+token_print_cb(void *p_void) {
+ Token *p_token = p_void;
+ printf("Token ");
+ token_print(p_token);
+ printf("\n");
+}
diff --git a/src/core/token.h b/src/core/token.h
new file mode 100644
index 0000000..b363279
--- /dev/null
+++ b/src/core/token.h
@@ -0,0 +1,183 @@
+/*:*
+ *: File: ./src/core/token.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, 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.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow 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 Paul Buetow 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 TOKEN_H
+#define TOKEN_H
+
+#include "../defines.h"
+
+#define IS_TERMINAL(t) (START_TERMINALS < t && t < END_TERMINALS)
+#define IS_NOT_TERMINAL(t) !IS_TERMINAL(t)
+#define IS_TYPE(t) (START_TYPES < t && t < END_TYPES)
+#define IS_NOT_TYPE(t) !IS_TYPE(t)
+#define IS_KEYWORD(t) (START_KEYWORDS < t && t < END_KEYWORDS)
+#define IS_NOT_KEYWORD(t) !IS_KEYWORD(t)
+#define IS_OPERATOR(t) (START_OPERATORS < t && t < END_OPERATORS)
+#define IS_NOT_OPERATOR(t) !IS_OPERATOR(t)
+#define IS_NON_TERMINAL(t) (START_NON_TERMINALS < t && t < END_NON_TERMINALS)
+#define IS_NOT_NON_TERMINAL(t) !IS_NON_TERMINAL(t)
+#define IS_IDENT(t) (t == TT_IDENT)
+#define IS_NOT_IDENT(t) !(IS_IDENT(t))
+#define IS_ASSIGNABLE(t) (START_ASSIGNABLES < t && t < END_ASSIGNABLES)
+#define IS_NUMERICAL(t) (START_NUMERICAL < t && t < END_NUMERICAL)
+#define IS_NOT_NUMERICAL(t) !(IS_NUMERICAL(t))
+
+#define token_get_filename(t) \
+ (t->c_filename != NULL ? t->c_filename : "Code string")
+#define token_get_line_nr(t) t->i_line_nr
+#define token_get_pos_nr(t) t->i_pos_nr
+#define token_get_tt(t) (t ? t->tt_cur : TT_NONE)
+#define token_get_val(t) t->c_val
+#define token_get_ival(t) t->i_val
+#define token_get_dval(t) t->d_val
+#define token_set_tt(t,tt) t->tt_cur = tt
+#define token_set_val(t,c) t->c_val = c
+#define token_set_ival(t,i) t->i_val = i
+#define token_set_dval(t,d) t->d_val = d
+#define token_set_pos(t, l, p) t->i_line_nr = l; t->i_pos_nr = p
+#define token_get_posnr(t) t->i_pos_nr
+#define token_get_linenr(t) t->i_line_nr
+#define token_ref_up(t) ++t->i_ref_count
+#define token_ref_down(t) --t->i_ref_count
+
+typedef enum {
+ // Diverse
+ TT_NONE,
+ TT_END_OF_CODE,
+ TT_BOOL, // Temporaly disabled, maybe NUMERICAL in future again
+
+ // Diverse types
+ START_TERMINALS,
+ START_TYPES,
+ START_ASSIGNABLES,
+ START_NUMERICAL,
+ TT_INTEGER,
+ TT_DOUBLE,
+ END_NUMERICAL,
+ TT_STRING,
+ END_ASSIGNABLES,
+ TT_IDENT,
+ END_TYPES,
+
+ // Keywords
+ START_KEYWORDS,
+ TT_ELSE,
+ TT_BREAK,
+ TT_IF,
+ TT_IFNOT,
+ TT_RET,
+ TT_CONST,
+ TT_PROC,
+ TT_FUNC,
+ TT_MY,
+ TT_WHILE,
+ TT_UNTIL,
+ TT_NEXT,
+ TT_INT,
+ TT_DEFINED,
+ TT_UNDEF,
+ END_KEYWORDS,
+
+ START_PARANTS,
+ TT_PARANT_CL,
+ TT_PARANT_CR,
+ TT_PARANT_L,
+ TT_PARANT_R,
+ END_PARANTS,
+
+ // Operators
+ START_OPERATORS,
+ TT_ADD,
+ TT_AND,
+ TT_ASSIGN,
+ TT_COMMA,
+ TT_DDOT,
+ TT_DECR,
+ TT_DIV,
+ TT_DOT,
+ TT_EQ,
+ TT_GE,
+ TT_GT,
+ TT_INCR,
+ TT_LE,
+ TT_LSHIFT,
+ TT_LT,
+ TT_MULT,
+ TT_NEQ,
+ TT_NOT,
+ TT_NOTEQ,
+ TT_OR,
+ TT_RE,
+ TT_RSHIFT,
+ TT_SEMICOLON,
+ TT_SUB,
+ TT_VID,
+ TT_XOR,
+ END_OPERATORS,
+
+ END_TERMINALS,
+
+} TokenType;
+
+typedef struct {
+ TokenType tt_cur;
+ char *c_val;
+ int i_val;
+ double d_val;
+ int i_line_nr;
+ int i_pos_nr;
+ char *c_filename;
+ unsigned int u_token_id;
+ int i_ref_count;
+} Token;
+
+Token* token_new(char *c_val, TokenType tt_cur, int i_line_nr, int i_pos_nr, char *c_filename);
+Token* token_new_integer(int i_val);
+Token* token_new_couble(double d_val);
+Token* token_new_string(char *c_val);
+Token* token_new_copy(Token *p_token);
+Token* token_new_(char *c_val, TokenType tt_cur, char *c_filename);
+Token* token_new_dummy();
+void token_copy_vals(Token *p_token_to, Token *p_token_from);
+void token_delete(Token *p_token);
+void token_delete_cb(void *p_token);
+void token_ref_down_cb(void *p_token);
+void* token_copy_cb(void *p_token);
+char* tt_get_name(TokenType tt_cur);
+void token_print_cb(void *p_void);
+void token_print(Token *p_token);
+void token_print_val(Token *p_token);
+TokenType get_tt(char *c_token);
+
+#endif