diff options
| author | Paul Buetow <paul@buetow.org> | 2008-05-15 23:28:07 +0000 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2008-05-15 23:28:07 +0000 |
| commit | be839900419c7a74c4a46efd279d0ca16b35dc1f (patch) | |
| tree | 1355c8f238d1c58ffd5cb8803bcc2adf987e79aa /src/core | |
| parent | 33c945e58f86267b0d3bdca4c3421155e11eb0d9 (diff) | |
Moved stuff into trunk.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/convert.c | 185 | ||||
| -rw-r--r-- | src/core/convert.h | 53 | ||||
| -rw-r--r-- | src/core/function.c | 661 | ||||
| -rw-r--r-- | src/core/function.h | 50 | ||||
| -rw-r--r-- | src/core/garbage.c | 136 | ||||
| -rw-r--r-- | src/core/garbage.h | 54 | ||||
| -rw-r--r-- | src/core/interpret.c | 946 | ||||
| -rw-r--r-- | src/core/interpret.h | 75 | ||||
| -rw-r--r-- | src/core/scanner.c | 391 | ||||
| -rw-r--r-- | src/core/scanner.h | 71 | ||||
| -rw-r--r-- | src/core/scope.c | 150 | ||||
| -rw-r--r-- | src/core/scope.h | 59 | ||||
| -rw-r--r-- | src/core/symbol.c | 66 | ||||
| -rw-r--r-- | src/core/symbol.h | 64 | ||||
| -rw-r--r-- | src/core/token.c | 380 | ||||
| -rw-r--r-- | src/core/token.h | 183 |
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 |
