Showing
41 changed files
with
3705 additions
and
0 deletions
ChangeLog
0 → 100644
| 1 | +0.0.1: First test with a bison grammar and flex scanner. Process simple | |
| 2 | + statement as in the examples contained in the bison docs. | |
| 3 | +0.0.2: more work on grammar (add loops and conditionals, experiments), | |
| 4 | + also add tplparser.[ch] that serves for general purpose grammer | |
| 5 | + actions. | |
| 6 | +0.0.3: brought the grammar to a more or less final state. | |
| 7 | + Add several functions for procession different expressions. | |
| 8 | + Add variables. | |
| 9 | + Do some leak checking. | |
| 10 | +0.0.4: Finalize variables with adding support for arrays and hashes. | |
| 11 | + A word to variables: | |
| 12 | + - There is no need to declare a variable. As soon as one assigns | |
| 13 | + something to an identifier, that identifier holds that value. | |
| 14 | + - It is an error to use a variable that has no assigned value | |
| 15 | + within an expression. | |
| 16 | + - Assigning a new value to a variable simply overwrites its | |
| 17 | + previous content. There is no way to recover the previous | |
| 18 | + content. | |
| 19 | + - The above is also true if the variable was an array or hash. | |
| 20 | + - Variables can be of type INT, FLOAT or STRING. If you use | |
| 21 | + Variables or values of different type within an expression | |
| 22 | + implicit casts are done. For rules of implicit casts see below. | |
| 23 | + - There is actually no way to explicitly cast a variable, but that | |
| 24 | + may change in future. | |
| 25 | + - Rules for implicit casts are: | |
| 26 | + * normally the first operand of an expression specifies the | |
| 27 | + resulting type. All following operands are implicitly cast to | |
| 28 | + the type of the first operand. | |
| 29 | + * The only exception to this is if one of the operands is a | |
| 30 | + sting. Then all other operands are implicitly cast to string. | |
| 31 | + Again do some leak and memchecks. | |
| 32 | + | |
| 33 | +0.0.5: implement explicit casts | |
| 34 | + put all things in a sane autobuild package. | |
| 35 | + called the whole thing: tepal "TEpal is a template PArsing Library" | |
| 36 | + | |
| 37 | +0.0.6: 25/11/2006 lots of code cleanups to prepare to code to use AST | |
| 38 | + all expressions have now an own datatype. That reduces the grammar | |
| 39 | + file a lot (and makes it easier to keep it conflict-free) because | |
| 40 | + i do not need to distinguish between int, float and string in the | |
| 41 | + grammar right now. | |
| 42 | + Also expression computation has become much cleaned. | |
| 43 | + I also change the behaviour of freeing data. No function frees | |
| 44 | + any of it calling parameters. This results in a lot of | |
| 45 | + memory leaks right now. !!!IMPORTANT!!! That has to be fixed soon! | |
| 46 | + --- | |
| 47 | + Already fixed some leaks, but some still remain. | |
| 48 | + | |
| 49 | + 26/11/2006 more leaks resolved | |
| 50 | + well, right now no leaks remain when i use tepal with my test | |
| 51 | + index.html | |
| 52 | + --- | |
| 53 | + If an undefined variable is used an error message is given. | |
| 54 | + !!!FIXME!!! I need a way to maintain the complete variable identifier | |
| 55 | + to tell it with the error message. | |
| 56 | + | |
| 57 | +0.0.7: AST implemented | |
| 58 | + a very big step is done. An ast is implemented. Everything works as | |
| 59 | + before, but right now to demontrate the functionality of the ast also | |
| 60 | + if statements are computed correctly. | ... | ... |
Makefile.am
0 → 100644
NEWS
0 → 100644
README
0 → 100644
| 1 | +tepal is a Template Parsing Library, written in C. | |
| 2 | + | |
| 3 | +It's origin lies in my unhappieness with PHP, JSP and other | |
| 4 | +languages designed for web-development. Lately i learned a little | |
| 5 | +about template system and worked a little with smarty and after a | |
| 6 | +while i got the idea that if one wants to seperate program logic | |
| 7 | +from display logic it is also possible to write you application | |
| 8 | +in C as i prefer. The FastCGI interface is as fast or even faster than | |
| 9 | +the PHP interface. The only thing needed is a library that does the | |
| 10 | +same things as smarty, set template variables, parse a template and | |
| 11 | +write the result. | |
| 12 | + | |
| 13 | +Well, it turns out that this only thing was more work than i first | |
| 14 | +thought, especially because i never wrote an interpreter or compiler | |
| 15 | +before. And i had not college courses on that issue too. So i had to | |
| 16 | +find out everything by my own. Thanks go to the excellent documentation | |
| 17 | +of flex and bison and the Telos GmbH that published a simple interpreter. | |
| 18 | + | |
| 19 | +While i was writing this I recognised that it might be usefull at other | |
| 20 | +things too. Everything that can be created by a cleartext template | |
| 21 | +and some application logic can be created with this lib. | ... | ... |
TODO
0 → 100644
| 1 | +for version 0.0.* | |
| 2 | + | |
| 3 | +- implement blocks | |
| 4 | + * every block has to have its own identifier list. Additional | |
| 5 | + a reference to to the upper block should be part of a block | |
| 6 | + to realize variable lookup in upper blocks. | |
| 7 | + * every block contains a statement list, that hold all statements | |
| 8 | + that occured within the block. | |
| 9 | + * a block is as itself a statement, that could be part of a statement | |
| 10 | + list. | |
| 11 | + * blocklocal, global and parent variables | |
| 12 | + variables in general are block local. This means, using varable a | |
| 13 | + within a sub-block does not affect an existing variable a within a | |
| 14 | + parent block. | |
| 15 | + Every block can contain one optional globals declaration section. This | |
| 16 | + is a special block, wich declares identifiers to be used as global | |
| 17 | + (topmost block) identifiers. If a non-existent identifier is deklared | |
| 18 | + in such a section a global variable is created. | |
| 19 | + Additionally there will be a _parent_ operator for use with an identifier. | |
| 20 | + This will allow one to access a variable used (and therefor deklared) | |
| 21 | + somewhere above the local block. If no variable with this identifier can | |
| 22 | + be found an error message is shown and processing will stop. | |
| 23 | + | |
| 24 | +- implement loops and conditionals | |
| 25 | + * first the statement directly following the loop or conditional | |
| 26 | + tokens is saved. | |
| 27 | + * the this is executed 0..n times depending on the loop or conditional. | |
| 28 | + | |
| 29 | +- ich habe herausgefunden das alle Ausdrücken in denen Variablen vorkommen | |
| 30 | + auch in einen statement stack aufgenommen werden müssen. Nur konstante | |
| 31 | + Ausdrücken können direkt ausgewertet werden und muessen nicht in | |
| 32 | + den AST (abstract statement tree, ist faktisch aber eher ein stack da | |
| 33 | + jeder branch unmittelbar ausgeführt wird). Ups, sorry this is | |
| 34 | + accidently german. | |
| 35 | + | |
| 36 | +- Add an interface to access the variable space of the interpreter from | |
| 37 | + within a C program in an easy way. | |
| 38 | + | |
| 39 | +- add CGI-lib for parsing of requests. | |
| 40 | + | |
| 41 | +- write a first test-webapp. | |
| 42 | + | |
| 43 | +- code cleanups | |
| 44 | + | |
| 45 | +- comment the code more completely. | |
| 46 | + | |
| 47 | +- date Datentyp hinzufügen | |
| 48 | + | |
| 49 | +- Modifizierer für das Ausgabeformat hinzufügen. | |
| 50 | + | |
| 51 | +=> we come to version 0.1.0 | |
| 52 | +========================================================================= | |
| 53 | + | |
| 54 | +for version 0.1.* | |
| 55 | + | |
| 56 | +- implement Sessions | |
| 57 | + * How to work with cookies? | |
| 58 | + * Sessionvariables will be saves within a BerkDB. | |
| 59 | + | |
| 60 | +- maybe begin of an application-server, that preserves the state of an | |
| 61 | + application between its calls via cgi. | |
| 62 | + | |
| 63 | +- allow and implement includes within templates. | ... | ... |
autoclean.sh
0 → 100755
| 1 | +#!/bin/sh | |
| 2 | +# Script for cleaning all autogenerated files. | |
| 3 | + | |
| 4 | +test ! -f Makefile || make distclean | |
| 5 | + | |
| 6 | +# Generated by aclocal. | |
| 7 | +rm -f aclocal.m4 | |
| 8 | + | |
| 9 | +# Generated by autoconf. | |
| 10 | +rm -f configure | |
| 11 | + | |
| 12 | +# Generated by autoheader | |
| 13 | +rm -f config.h.in | |
| 14 | + | |
| 15 | +# Generated or brought in by automake. | |
| 16 | +rm -f Makefile.in | |
| 17 | +rm -f src/Makefile.in | |
| 18 | +rm -f include/Makefile.in | |
| 19 | +rm -f INSTALL | |
| 20 | +rm -f COPYING | |
| 21 | + | |
| 22 | +# Generated by all in config | |
| 23 | +rm -rf config | |
| 24 | + | |
| 25 | +rm -rf autom4te.cache | ... | ... |
autogen.sh
0 → 100755
configure.ac
0 → 100644
| 1 | +AC_PREREQ(2.59) | |
| 2 | +AC_INIT(tepal, 0.0.7, georg@steffers.org) | |
| 3 | +AC_CONFIG_AUX_DIR([config]) | |
| 4 | +AC_CONFIG_SRCDIR([src/tepal.c]) | |
| 5 | +AC_CONFIG_HEADER([config.h]) | |
| 6 | +AM_INIT_AUTOMAKE | |
| 7 | + | |
| 8 | +AC_CANONICAL_HOST | |
| 9 | + | |
| 10 | +# Checks for programs. | |
| 11 | +AC_PROG_CC | |
| 12 | +AC_PROG_MAKE_SET | |
| 13 | +AC_LIBTOOL_WIN32_DLL | |
| 14 | +AC_PROG_LIBTOOL | |
| 15 | +AC_PROG_YACC | |
| 16 | +AC_PROG_LEX | |
| 17 | + | |
| 18 | +# Checks for header files. | |
| 19 | +AC_HEADER_STDC | |
| 20 | +AC_CHECK_HEADERS([libintl.h locale.h stdlib.h string.h unistd.h wchar.h]) | |
| 21 | + | |
| 22 | +# Checks for libraries. | |
| 23 | +AC_MSG_CHECKING([for Win32]) | |
| 24 | +case "$host" in | |
| 25 | + *-*-mingw*) | |
| 26 | + win32="yes, use windows threads" | |
| 27 | + ;; | |
| 28 | + *) | |
| 29 | + win32="no" | |
| 30 | + ;; | |
| 31 | +esac | |
| 32 | +AC_MSG_RESULT([$win32]) | |
| 33 | + | |
| 34 | +AM_CONDITIONAL(WIN32, test "x$win32" != "xno") | |
| 35 | + | |
| 36 | +# Checks for typedefs, structures, and compiler characteristics. | |
| 37 | +AC_C_CONST | |
| 38 | + | |
| 39 | +# Checks for library functions. | |
| 40 | +AC_CHECK_FUNCS([memset setlocale]) | |
| 41 | + | |
| 42 | +AC_CONFIG_FILES([Makefile]) | |
| 43 | +AC_CONFIG_FILES([src/Makefile]) | |
| 44 | +AC_CONFIG_FILES([include/Makefile]) | |
| 45 | + | |
| 46 | +AC_OUTPUT | ... | ... |
include/Makefile.am
0 → 100644
include/assign.h
0 → 100644
include/bbtree.h
0 → 100644
| 1 | +#ifndef _BBTREE_H_ | |
| 2 | +#define _BBTREE_H_ | |
| 3 | + | |
| 4 | +/* this is only here for testing. In final version | |
| 5 | + * it should be in bbtree.c */ | |
| 6 | +typedef | |
| 7 | +struct bbTreeNode | |
| 8 | +{ | |
| 9 | + void * value; | |
| 10 | + | |
| 11 | + long height; | |
| 12 | + | |
| 13 | + struct bbTreeNode * left; | |
| 14 | + struct bbTreeNode * right; | |
| 15 | + | |
| 16 | +} s_bbTreeNode; | |
| 17 | + | |
| 18 | +#define BBTREE_LEFT_HEIGHT(t) ((t)->left ? (t)->left->height : -1) | |
| 19 | +#define BBTREE_RIGHT_HEIGHT(t) ((t)->right ? (t)->right->height : -1) | |
| 20 | +#define BBTREE_AVL(t) (BBTREE_RIGHT_HEIGHT ((t)) - \ | |
| 21 | + BBTREE_LEFT_HEIGHT ((t))) | |
| 22 | + | |
| 23 | + | |
| 24 | +/* | |
| 25 | + * comparison for tree-node values. | |
| 26 | + * Has to be defined by user and set | |
| 27 | + * with bbTreeNew. | |
| 28 | + * | |
| 29 | + * params: | |
| 30 | + * left: pointer to left value | |
| 31 | + * right: pointer to right value | |
| 32 | + * | |
| 33 | + * returns: | |
| 34 | + * 0: if values equal | |
| 35 | + * 1: if right greater left | |
| 36 | + * -1: if left greater right | |
| 37 | + */ | |
| 38 | +typedef int (* t_bbTreeCmp) (void *, void *); | |
| 39 | + | |
| 40 | +typedef | |
| 41 | +struct bbTree | |
| 42 | +{ | |
| 43 | + struct bbTreeNode * root; | |
| 44 | + | |
| 45 | + t_bbTreeCmp cmp; | |
| 46 | +} s_bbTree; | |
| 47 | + | |
| 48 | + | |
| 49 | +/* constructor, destructor */ | |
| 50 | +s_bbTree * bbTreeNew (t_bbTreeCmp); | |
| 51 | +void bbTreeFree (s_bbTree *); | |
| 52 | + | |
| 53 | +/* data manipulation */ | |
| 54 | +void * bbTreeInsert (s_bbTree *, void *); | |
| 55 | +void * bbTreeSeek (s_bbTree *, void *); | |
| 56 | +void * bbTreeRemove (s_bbTree *, void *); | |
| 57 | + | |
| 58 | +/* analysation */ | |
| 59 | +void * bbTreeMin (s_bbTree *); | |
| 60 | +void * bbTreeMax (s_bbTree *); | |
| 61 | +int bbTreeSize (s_bbTree *); | |
| 62 | + | |
| 63 | +/* bbTree to other Datastructure */ | |
| 64 | +void ** bbTreeInOrder (s_bbTree *, void **); | |
| 65 | + | |
| 66 | +#endif /* _BBTREE_H_ */ | ... | ... |
include/block.h
0 → 100644
| 1 | +#ifndef _BLOCK_H_ | |
| 2 | +#define _BLOCK_H_ | |
| 3 | + | |
| 4 | +typedef struct block s_block; | |
| 5 | + | |
| 6 | +#include <identList.h> | |
| 7 | +#include <stmtQueue.h> | |
| 8 | + | |
| 9 | +s_block * blockNew (s_stmtQueue *); | |
| 10 | +void blockFree (s_block *); | |
| 11 | +void blockSetNonLocalId (s_block *, s_ident *); | |
| 12 | +s_block * blockPush (s_block **, s_block *); | |
| 13 | +s_block * blockPop (s_block **); | |
| 14 | +s_block * blockPrev (s_block *); | |
| 15 | +s_stmtQueue * blockStmts (s_block *); | |
| 16 | +s_identList * blockIdl (s_block *); | |
| 17 | + | |
| 18 | +#endif /* _BLOCK_H_ */ | ... | ... |
include/cast.h
0 → 100644
include/evalCond.h
0 → 100644
include/evalExpr.h
0 → 100644
| 1 | +#ifndef _EVAL_EXPR_H_ | |
| 2 | +#define _EVAL_EXPR_H_ | |
| 3 | + | |
| 4 | +#include <tepal_pars.h> | |
| 5 | +#include <expValue.h> | |
| 6 | + | |
| 7 | +#define PLUS '+' | |
| 8 | +#define MINUS '-' | |
| 9 | +#define TIMES '*' | |
| 10 | +#define OVER '/' | |
| 11 | +#define MODULO '%' | |
| 12 | + | |
| 13 | +s_expVal * evalExpr (int, s_expVal *, s_expVal *); | |
| 14 | + | |
| 15 | +#endif /* _EVAL_EXPR_H_ */ | ... | ... |
include/expValue.h
0 → 100644
| 1 | +#ifndef _EXP_VALUE_H_ | |
| 2 | +#define _EXP_VALUE_H_ | |
| 3 | + | |
| 4 | +#define EXP_TYP_INT 'i' | |
| 5 | +#define EXP_TYP_FLOAT 'f' | |
| 6 | +#define EXP_TYP_STRING 's' | |
| 7 | + | |
| 8 | +/* Typdeklaration, etc */ | |
| 9 | +typedef struct expVal s_expVal; | |
| 10 | + | |
| 11 | + | |
| 12 | +/* Constructoren / Destructoren */ | |
| 13 | +s_expVal * expValueIntNew (long); | |
| 14 | +s_expVal * expValueFloatNew (double); | |
| 15 | +s_expVal * expValueStringNew (char *); | |
| 16 | + | |
| 17 | +s_expVal * expValueClone (s_expVal *); | |
| 18 | + | |
| 19 | +void expValueFree (s_expVal *); | |
| 20 | + | |
| 21 | + | |
| 22 | +/* Accessors */ | |
| 23 | +long expValueInt (s_expVal *); | |
| 24 | +double expValueFloat (s_expVal *); | |
| 25 | +char * expValueString (s_expVal *); | |
| 26 | + | |
| 27 | +/* analyse expValue */ | |
| 28 | +int expValueGetType (s_expVal *); | |
| 29 | + | |
| 30 | + | |
| 31 | +#endif /* _EXP_VALUE_H_ */ | ... | ... |
include/helper.h
0 → 100644
include/ident.h
0 → 100644
| 1 | +#ifndef _IDENT_H_ | |
| 2 | +#define _IDENT_H_ | |
| 3 | + | |
| 4 | +#define ID_TYP_UNDEF 'n' | |
| 5 | +#define ID_TYP_EXP 'e' | |
| 6 | +#define ID_TYP_IDL 'L' | |
| 7 | + | |
| 8 | +struct ident; | |
| 9 | +typedef struct ident s_ident; | |
| 10 | + | |
| 11 | +#include <expValue.h> | |
| 12 | +#include <identList.h> | |
| 13 | + | |
| 14 | +/* identifier constructors/destructors */ | |
| 15 | +s_ident * identNew (int, const char *); | |
| 16 | +s_ident * identUndefNew (int, const char *); | |
| 17 | +s_ident * identExpNew (int, const char *, s_expVal *); | |
| 18 | +s_ident * identIdlNew (int, const char *, s_identList *); | |
| 19 | +void identFree (s_ident *); | |
| 20 | + | |
| 21 | +/* analyse ident */ | |
| 22 | +int identIsQueued (s_ident *); | |
| 23 | +void identEnqueue (s_ident *); | |
| 24 | +void identDequeue (s_ident *); | |
| 25 | +int identGetType (s_ident *); | |
| 26 | +char * identGetKey (s_ident *); | |
| 27 | +int identGetIdx (s_ident *); | |
| 28 | + | |
| 29 | +/* identifier to value */ | |
| 30 | +s_expVal * identExp (s_ident *); | |
| 31 | +s_identList * identIdl (s_ident *); | |
| 32 | +s_ident * identSetExp (s_ident *, s_expVal *); | |
| 33 | +s_ident * identSetIdl (s_ident *, s_identList *); | |
| 34 | + | |
| 35 | +#endif /* _IDENT_H_ */ | ... | ... |
include/identList.h
0 → 100644
| 1 | +#ifndef _IDENT_LIST_H_ | |
| 2 | +#define _IDENT_LIST_H_ | |
| 3 | + | |
| 4 | +typedef struct identList s_identList; | |
| 5 | + | |
| 6 | +#include <ident.h> | |
| 7 | +#include <expValue.h> | |
| 8 | + | |
| 9 | +/* constructor/destructor for new identList */ | |
| 10 | +s_identList * identListNew (void); | |
| 11 | +void identListFree (s_identList *); | |
| 12 | + | |
| 13 | +/* insertions or deletion into a list */ | |
| 14 | +s_ident * identListPutVal (s_identList *, s_ident *); | |
| 15 | +s_ident * identListPutExpByIdx (s_identList *, int, s_expVal *); | |
| 16 | +s_ident * identListPutIdlByIdx (s_identList *, int, s_identList *); | |
| 17 | +s_ident * identListPutExpByKey (s_identList *, const char *, s_expVal *); | |
| 18 | +s_ident * identListPutIdlByKey (s_identList *, const char *, s_identList *); | |
| 19 | +void identListRemoveByIdx (s_identList *, int); | |
| 20 | +void identListRemoveByKey (s_identList *, const char *); | |
| 21 | + | |
| 22 | +/* seeking in list */ | |
| 23 | +s_ident * identListSeekIdx (s_identList *, int); | |
| 24 | +s_ident * identListSeekKey (s_identList *, const char *); | |
| 25 | + | |
| 26 | +/* identList to other DataStructures */ | |
| 27 | +s_ident ** identListToArray (s_identList *); | |
| 28 | + | |
| 29 | +#endif /* _IDENT_LIST_H_ */ | ... | ... |
include/statement.h
0 → 100644
| 1 | +#ifndef _STMT_H_ | |
| 2 | +#define _STMT_H_ | |
| 3 | + | |
| 4 | +#define STMT_CONST 0 | |
| 5 | +#define STMT_BLOCK 1 | |
| 6 | + | |
| 7 | +#define STMT_PRINT 10 | |
| 8 | +#define STMT_IF 11 | |
| 9 | +#define STMT_FOREACH 12 | |
| 10 | +#define STMT_REPEAT 13 | |
| 11 | +#define STMT_ASSIGN 14 | |
| 12 | +#define STMT_UNSET 15 | |
| 13 | + | |
| 14 | +#define STMT_EVAL_PLUS 20 | |
| 15 | +#define STMT_EVAL_MINUS 21 | |
| 16 | +#define STMT_EVAL_TIMES 22 | |
| 17 | +#define STMT_EVAL_OVER 23 | |
| 18 | +#define STMT_EVAL_MODULO 24 | |
| 19 | +#define STMT_EVAL_NEG 25 | |
| 20 | + | |
| 21 | +#define STMT_IDENT_VAR 30 | |
| 22 | +#define STMT_IDENT_ARRAY 31 | |
| 23 | +#define STMT_IDENT_VAL 32 | |
| 24 | + | |
| 25 | +#define STMT_CAST_INT 40 | |
| 26 | +#define STMT_CAST_FLOAT 41 | |
| 27 | +#define STMT_CAST_STRING 42 | |
| 28 | + | |
| 29 | +#define STMT_COMP_EQ 50 | |
| 30 | +#define STMT_COMP_NE 51 | |
| 31 | +#define STMT_COMP_LT 52 | |
| 32 | +#define STMT_COMP_GT 53 | |
| 33 | +#define STMT_COMP_LE 54 | |
| 34 | +#define STMT_COMP_GE 55 | |
| 35 | + | |
| 36 | +#define STMT_COND_EXPR 60 | |
| 37 | +#define STMT_COND_AND 61 | |
| 38 | +#define STMT_COND_OR 62 | |
| 39 | +#define STMT_COND_NEG 63 | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | +#define STYP_NONE 0 | |
| 44 | +#define STYP_COND 1 | |
| 45 | +#define STYP_EVAL 2 | |
| 46 | +#define STYP_IDVAL 3 | |
| 47 | + | |
| 48 | +/* | |
| 49 | + * Deklaration und Definition | |
| 50 | + */ | |
| 51 | +union stmtType | |
| 52 | +{ | |
| 53 | + int cond; | |
| 54 | + struct expVal * eVal; | |
| 55 | + struct ident * idVal; | |
| 56 | +}; | |
| 57 | + | |
| 58 | +typedef struct stmt s_stmt; | |
| 59 | +typedef union stmtType u_stmtType; | |
| 60 | + | |
| 61 | +#include <stmtQueue.h> | |
| 62 | +#include <block.h> | |
| 63 | + | |
| 64 | +/* | |
| 65 | + * Interface | |
| 66 | + */ | |
| 67 | +s_stmt * stmtNew (int, s_stmtQueue *, int, u_stmtType); | |
| 68 | +void stmtFree (s_stmt *); | |
| 69 | +s_stmtQueue * stmtGetArgs (s_stmt *); | |
| 70 | +u_stmtType stmtGetVal (s_stmt *); | |
| 71 | +int stmtGetConstTyp (s_stmt *); | |
| 72 | +u_stmtType stmtDo (s_stmt *, s_block *); | |
| 73 | + | |
| 74 | +#endif /* _STMT_H_ */ | ... | ... |
include/stmtQueue.h
0 → 100644
| 1 | +#ifndef _STMT_QUEUE_H_ | |
| 2 | +#define _STMT_QUEUE_H_ | |
| 3 | + | |
| 4 | +#include <ident.h> | |
| 5 | + | |
| 6 | +typedef struct stmtQueue s_stmtQueue; | |
| 7 | + | |
| 8 | +#include <statement.h> | |
| 9 | + | |
| 10 | +s_stmtQueue * stmtQueueNew (void); | |
| 11 | +void stmtQueueFree (s_stmtQueue *); | |
| 12 | + | |
| 13 | +void stmtQueueEnqueue (s_stmtQueue *, s_stmt *); | |
| 14 | +s_stmt * stmtQueueDequeue (s_stmtQueue *); | |
| 15 | +s_stmtQueue * stmtQueueConcat (s_stmtQueue *, s_stmtQueue *); | |
| 16 | + | |
| 17 | +s_stmt * stmtQueueGet (s_stmtQueue *, unsigned int); | |
| 18 | +void stmtQueueDo (s_stmtQueue *); | |
| 19 | + | |
| 20 | +unsigned int stmtQueueGetSize (s_stmtQueue *); | |
| 21 | + | |
| 22 | +#endif /* _STMT_QUEUE_H_ */ | ... | ... |
include/tepal.h
0 → 100644
| 1 | +#ifndef __HTMLPARS_H__ | |
| 2 | +#define __HTMLPARS_H__ | |
| 3 | + | |
| 4 | +#include "expValue.h" | |
| 5 | + | |
| 6 | +#define ERR_UNDEF_VAR 0 | |
| 7 | +#define ERR_NO_INDEX 1 | |
| 8 | +#define ERR_STRING_OPERATOR 2 | |
| 9 | +#define ERR_FLOAT_OPERATOR 3 | |
| 10 | + | |
| 11 | +void exitError (int, ...); | |
| 12 | +void printExpr (s_expVal *); | |
| 13 | + | |
| 14 | +#endif /* __HTMLPARS_H__ */ | ... | ... |
include/variable.h
0 → 100644
index.tpl
0 → 100644
| 1 | +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" | |
| 2 | + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | |
| 3 | +<html xmlns="http://www.w3.org/1999/xhtml"> | |
| 4 | + <head> | |
| 5 | + <title>Test Page for Apache Installation</title> | |
| 6 | + </head> | |
| 7 | + | |
| 8 | + <body> | |
| 9 | + <p>If you can see this, it means that the installation of the <a | |
| 10 | + href="http://www.apache.org/foundation/preFAQ.html">Apache web server</a> | |
| 11 | + software on this system was successful. You may now add content to this | |
| 12 | + directory and replace this page.</p> | |
| 13 | + | |
| 14 | + <hr style="width: <# 100 #>%; height: 3px;" /> | |
| 15 | + | |
| 16 | + <h2 style="text-align: center">Seeing this instead of the website you expected?</h2> | |
| 17 | + | |
| 18 | + <# "[Ausdruck 5 + 5] " + (5 + 5) + eol #> | |
| 19 | + | |
| 20 | + <# if (! 'HALLO' == 'HALLO'): #> | |
| 21 | + <p>This page is here because the site administrator has changed the | |
| 22 | + configuration of this web server. Please <strong>contact the person | |
| 23 | + responsible for maintaining this server with questions.</strong> | |
| 24 | + The Apache Software Foundation, which wrote the web server software | |
| 25 | + this site administrator is using, has nothing to do with | |
| 26 | + maintaining this site and cannot help resolve configuration | |
| 27 | + issues.</p> | |
| 28 | + <# end #> | |
| 29 | + | |
| 30 | + <# | |
| 31 | + if (! (12 < 13 && 12 < 10)) | |
| 32 | + | |
| 33 | + : | |
| 34 | + "[Zuweisung yahoo = 15] " + eol; yahoo = 15; | |
| 35 | + "[Ausdruck yahoo] " + yahoo + eol; | |
| 36 | + | |
| 37 | + end | |
| 38 | + | |
| 39 | + "[Ausdruck 10 % 3] " + (10 % 3) + eol;;;; | |
| 40 | + "[Ausdruck 12.3 - 18] " + (12.3 - 18) + eol; | |
| 41 | + "[Ausdruck -47.78] " + -47.78 + eol; | |
| 42 | + "[Ausdruck 'HALLO'] " + 'HALLO' + eol; | |
| 43 | + '[Ausdruck -"WALLO"] ' + -"WALLO" + eol; | |
| 44 | + "[Ausdruck 'hokus ' + 'pokus'] " + ('hokus ' + 'pokus') + eol; | |
| 45 | + | |
| 46 | + repeat (bla count=10) | |
| 47 | + "[Ausdruck 32.56 * 10] " + 32.56 * 10 + eol; | |
| 48 | + | |
| 49 | + "[Zuweisung a = 250]" + eol; a = 250; | |
| 50 | + "[Zuweisung b=3.4-0.9]" + eol; b=3.4-0.9; | |
| 51 | + '[Zuweisung z="bla" + "bla"]' + eol; z="bla" + "bla"; | |
| 52 | + | |
| 53 | + "[Ausdruck a] " + a + eol; | |
| 54 | + "[Ausdruck a*10 + a*2] " + (a*10 + a*2) + eol; | |
| 55 | + | |
| 56 | + "[Zuweisung a = -'Georg']" + eol; a = -'Georg'; | |
| 57 | + "[Ausdruck -a] " + -a + eol; | |
| 58 | + "[Ausdruck a] " + a + eol; | |
| 59 | + | |
| 60 | + if (a == b) | |
| 61 | + "[Ausdruck 152 - 38] " + (152 - 38) + eol; | |
| 62 | + else | |
| 63 | + "[Ausdruck 'Harry' + -'hcsriH'] " + 'Harry' + -'hcsriH' + eol; | |
| 64 | + | |
| 65 | + foreach (harry as key, val): end | |
| 66 | + | |
| 67 | + "[Zuweisung jo ['terror'][12] = 53] " + eol; jo ['terror'][12] = 53; | |
| 68 | + "[Zuweisung onken = 'Falada']" + eol; onken = 'Falada'; | |
| 69 | + "[Ausdruck onken + jo ['terror'][12]] " + (onken + jo['terror'][12]) + eol; | |
| 70 | + "[Zuweisung toll[42] = 'Jedi']" + eol; toll[42] = 'Jedi'; | |
| 71 | + "[Ausdruck -toll[42]] " + -toll[42] + eol; | |
| 72 | + | |
| 73 | + "[Zuweisung harry = 12.0]" + eol; harry = 12.0; | |
| 74 | + "[Ausdruck harry*32] " + (harry*32) + eol; | |
| 75 | + "[Zuweisung dieter = 0]" + eol; dieter = 0; | |
| 76 | + "[Ausdruck 12.4+dieter] " + (12.4+dieter) + eol; | |
| 77 | + "[Zuweisung bonbon = 0.12]" + eol; bonbon = 0.12; | |
| 78 | + '[Ausdruck "Knall"+bonbon] ' + "Knall"+bonbon + eol; | |
| 79 | + "[Zuweisung mann = 'Mann']" + eol; mann = 'Mann'; | |
| 80 | + "[Zuweisung oh = '-o-']" + eol; oh = '-o-'; | |
| 81 | + "[Ausdruck mann+oh+mann] " + (mann+oh+mann) + eol; | |
| 82 | + '[Ausdruck 13 + "5"] ' + (13 + "5") + eol; | |
| 83 | + '[Ausdruck "Hallo" + 12] ' + ("Hallo" + 12) + eol; | |
| 84 | + '[Ausdruck b + (int) "32"] ' + (b + (int) "32") + eol; | |
| 85 | + #> | |
| 86 | + | |
| 87 | + <hr style="width: 100%; height: 3px;" /> | |
| 88 | + | |
| 89 | + <# repeat (hoho count=100) #> | |
| 90 | + <p>The Apache documentation is available | |
| 91 | + <a href="http://httpd.apache.org/docs-2.0/">online</a> or has been installed | |
| 92 | + <a href="/manual/">locally</a>.</p> | |
| 93 | + | |
| 94 | + <# foreach (jokus as key, val): #> | |
| 95 | + <p>You are free to use the image below on an Apache-powered web | |
| 96 | + server. Thanks for using Apache!</p> | |
| 97 | + <# end #> | |
| 98 | + | |
| 99 | + <div style="text-align: center"><img src="apache_pb.gif" alt="" /></div> | |
| 100 | + </body> | |
| 101 | +</html> | ... | ... |
src/Makefile.am
0 → 100644
| 1 | +tepal_source = tepal.c tepal_pars.c tepal_scan.c \ | |
| 2 | + evalExpr.c evalCond.c expValue.c \ | |
| 3 | + variable.c assign.c cast.c \ | |
| 4 | + ident.c identList.c bbtree.c \ | |
| 5 | + statement.c stmtQueue.c block.c | |
| 6 | + | |
| 7 | +nobase_include_HEADERS = tepal_pars.y tepal_scan.l | |
| 8 | + | |
| 9 | +BUILT_SOURCES = tepal_pars.c tepal_scan.c | |
| 10 | +CLEANFILES = tepal_pars.c tepal_scan.c ../include/tepal_pars.h | |
| 11 | + | |
| 12 | + | |
| 13 | +bin_PROGRAMS = tepal | |
| 14 | + | |
| 15 | +tepal_SOURCES = $(tepal_source) | |
| 16 | +tepal_CFLAGS = -I../include | |
| 17 | + | |
| 18 | +tepal_pars.c: Makefile tepal_pars.y | |
| 19 | + $(YACC) -d tepal_pars.y | |
| 20 | + mv y.tab.c tepal_pars.c | |
| 21 | + mv y.tab.h ../include/tepal_pars.h | |
| 22 | + | |
| 23 | +tepal_scan.c: Makefile tepal_scan.l | |
| 24 | + $(LEX) tepal_scan.l | |
| 25 | + mv lex.yy.c tepal_scan.c | ... | ... |
src/assign.c
0 → 100644
| 1 | +#include <stdio.h> | |
| 2 | +#include <malloc.h> | |
| 3 | +#include <stdlib.h> | |
| 4 | + | |
| 5 | +#include <expValue.h> | |
| 6 | +#include <ident.h> | |
| 7 | +#include <assign.h> | |
| 8 | +#include <tepal.h> | |
| 9 | + | |
| 10 | + s_expVal * | |
| 11 | +assign (s_ident * to, s_expVal * from) | |
| 12 | +{ | |
| 13 | + if (identGetType (to) == ID_TYP_IDL) | |
| 14 | + { | |
| 15 | + char * key = identGetKey (to); | |
| 16 | + exitError (ERR_NO_INDEX, key); | |
| 17 | + } | |
| 18 | + | |
| 19 | + /* !!!IMPORTANT!!! work here */ | |
| 20 | + /*identListPutVal (block, to);*/ | |
| 21 | + identSetExp (to, from); | |
| 22 | + | |
| 23 | + return from; | |
| 24 | +} | ... | ... |
src/bbtree.c
0 → 100644
| 1 | +/* | |
| 2 | + * bbTree (balanced binary tree) | |
| 3 | + */ | |
| 4 | +#include <malloc.h> | |
| 5 | +#include <stdio.h> | |
| 6 | +#include <string.h> | |
| 7 | + | |
| 8 | +#include <helper.h> | |
| 9 | +#include <bbtree.h> | |
| 10 | + | |
| 11 | + | |
| 12 | +/* | |
| 13 | + * statisch Funktionen | |
| 14 | + */ | |
| 15 | +static | |
| 16 | + s_bbTreeNode * | |
| 17 | +bbTreeNodeNew (void * value) | |
| 18 | +{ | |
| 19 | + s_bbTreeNode * new = (s_bbTreeNode *) malloc (sizeof (s_bbTreeNode)); | |
| 20 | + | |
| 21 | + new->value = value; | |
| 22 | + new->left = NULL; | |
| 23 | + new->right = NULL; | |
| 24 | + new->height = 0; | |
| 25 | + | |
| 26 | + return new; | |
| 27 | +} | |
| 28 | + | |
| 29 | +static | |
| 30 | + void | |
| 31 | +bbTreeNodeFree (s_bbTreeNode * t) | |
| 32 | +{ | |
| 33 | + if (t == NULL) | |
| 34 | + return; | |
| 35 | + | |
| 36 | + while (t->left != NULL) | |
| 37 | + { | |
| 38 | + bbTreeNodeFree (t->left); | |
| 39 | + t->left = NULL; | |
| 40 | + } | |
| 41 | + | |
| 42 | + while (t->right != NULL) | |
| 43 | + { | |
| 44 | + bbTreeNodeFree (t->right); | |
| 45 | + t->right = NULL; | |
| 46 | + } | |
| 47 | + | |
| 48 | + free (t); | |
| 49 | +} | |
| 50 | + | |
| 51 | +static | |
| 52 | + void | |
| 53 | +bbTreeNodeRotLeft (s_bbTreeNode * node) | |
| 54 | +{ | |
| 55 | + s_bbTreeNode * left = node->left; | |
| 56 | + s_bbTreeNode * right = node->right; | |
| 57 | + void * value = node->value; | |
| 58 | + | |
| 59 | + node->right = right->right; | |
| 60 | + node->left = right; | |
| 61 | + right->right = right->left; | |
| 62 | + right->left = left; | |
| 63 | + | |
| 64 | + node->value = right->value; | |
| 65 | + right->value = value; | |
| 66 | + | |
| 67 | + node->right->height = | |
| 68 | + 1 + MAX (BBTREE_LEFT_HEIGHT (node->left), | |
| 69 | + BBTREE_RIGHT_HEIGHT (node->left)); | |
| 70 | +} | |
| 71 | + | |
| 72 | +static | |
| 73 | + void | |
| 74 | +bbTreeNodeRotRight (s_bbTreeNode * node) | |
| 75 | +{ | |
| 76 | + s_bbTreeNode * left = node->left; | |
| 77 | + s_bbTreeNode * right = node->right; | |
| 78 | + void * value = node->value; | |
| 79 | + | |
| 80 | + node->left = left->left; | |
| 81 | + node->right = left; | |
| 82 | + left->left = left->right; | |
| 83 | + left->right = right; | |
| 84 | + | |
| 85 | + node->value = left->value; | |
| 86 | + left->value = value; | |
| 87 | + | |
| 88 | + node->right->height = | |
| 89 | + 1 + MAX (BBTREE_LEFT_HEIGHT (node->right), | |
| 90 | + BBTREE_RIGHT_HEIGHT (node->right)); | |
| 91 | +} | |
| 92 | + | |
| 93 | +static | |
| 94 | + void | |
| 95 | +bbTreeNodeBalance (s_bbTreeNode * node) | |
| 96 | +{ | |
| 97 | + if (BBTREE_AVL (node) == -2) | |
| 98 | + /* left is to long */ | |
| 99 | + { | |
| 100 | + if (BBTREE_AVL (node->left) == 1) | |
| 101 | + bbTreeNodeRotLeft (node->left); | |
| 102 | + bbTreeNodeRotRight (node); | |
| 103 | + } | |
| 104 | + | |
| 105 | + if (BBTREE_AVL (node) == -2) | |
| 106 | + /* right is to long */ | |
| 107 | + { | |
| 108 | + if (BBTREE_AVL (node->right) == 1) | |
| 109 | + bbTreeNodeRotRight (node->right); | |
| 110 | + bbTreeNodeRotLeft (node); | |
| 111 | + } | |
| 112 | +} | |
| 113 | + | |
| 114 | +/* | |
| 115 | + * This function returns either, NULL if a new node was inserted, or | |
| 116 | + * a node containing the old value if an existing node was modified. | |
| 117 | + */ | |
| 118 | +static | |
| 119 | + s_bbTreeNode * | |
| 120 | +bbTreeNodeInsert (s_bbTreeNode ** _node, t_bbTreeCmp cmp, void * value) | |
| 121 | +{ | |
| 122 | + s_bbTreeNode * node = *_node; | |
| 123 | + s_bbTreeNode * ret; | |
| 124 | + | |
| 125 | + if (node == NULL) | |
| 126 | + /* This happens only when bbTree::root is NULL | |
| 127 | + * on bbTreeInsert call */ | |
| 128 | + { | |
| 129 | + *_node = bbTreeNodeNew (value); | |
| 130 | + return NULL; | |
| 131 | + } | |
| 132 | + | |
| 133 | + if (cmp (value, node->value) == 0) | |
| 134 | + /* The key is already in the tree. | |
| 135 | + * In this case a node containing the old value is returned. */ | |
| 136 | + { | |
| 137 | + ret = bbTreeNodeNew (node->value); | |
| 138 | + node->value = value; | |
| 139 | + return ret; | |
| 140 | + } | |
| 141 | + | |
| 142 | + if (cmp (value, node->value) < 0) | |
| 143 | + if (node->left == NULL) | |
| 144 | + { | |
| 145 | + node->left = bbTreeNodeNew (value); | |
| 146 | + ret = NULL; | |
| 147 | + | |
| 148 | + if (BBTREE_AVL (node) == -2 || BBTREE_AVL (node) == 2) | |
| 149 | + bbTreeNodeBalance (node); | |
| 150 | + | |
| 151 | + node->height = 1 + MAX ( | |
| 152 | + BBTREE_LEFT_HEIGHT (node), BBTREE_RIGHT_HEIGHT (node)); | |
| 153 | + } | |
| 154 | + else | |
| 155 | + ret = bbTreeNodeInsert (&node->left, cmp, value); | |
| 156 | + | |
| 157 | + if (cmp (value, node->value) > 0) | |
| 158 | + if (node->right == NULL) | |
| 159 | + { | |
| 160 | + node->right = bbTreeNodeNew (value); | |
| 161 | + ret = NULL; | |
| 162 | + | |
| 163 | + if (BBTREE_AVL (node) == -2 || BBTREE_AVL (node) == 2) | |
| 164 | + bbTreeNodeBalance (node); | |
| 165 | + | |
| 166 | + node->height = 1 + MAX ( | |
| 167 | + BBTREE_LEFT_HEIGHT (node), BBTREE_RIGHT_HEIGHT (node)); | |
| 168 | + } | |
| 169 | + else | |
| 170 | + ret = bbTreeNodeInsert (&node->right, cmp, value); | |
| 171 | + | |
| 172 | + /* if we come here a new node was inserted a returned node | |
| 173 | + * containing {NULL, NULL} as value reflects this fact. */ | |
| 174 | + return ret; | |
| 175 | +} | |
| 176 | + | |
| 177 | +static | |
| 178 | + s_bbTreeNode * | |
| 179 | +bbTreeNodeSeek (s_bbTreeNode * node, t_bbTreeCmp cmp, void * value) | |
| 180 | +{ | |
| 181 | + if (node == NULL) | |
| 182 | + return NULL; | |
| 183 | + | |
| 184 | + if (cmp (value, node->value) == 0) | |
| 185 | + return node; | |
| 186 | + | |
| 187 | + if (cmp (value, node->value) < 0) | |
| 188 | + return bbTreeNodeSeek (node->left, cmp, value); | |
| 189 | + | |
| 190 | + if (cmp (value, node->value) > 0) | |
| 191 | + return bbTreeNodeSeek (node->right, cmp, value); | |
| 192 | + | |
| 193 | + return NULL; | |
| 194 | +} | |
| 195 | + | |
| 196 | +static | |
| 197 | + s_bbTreeNode * | |
| 198 | +bbTreeNodeMax (s_bbTreeNode * node) | |
| 199 | +{ | |
| 200 | + if (node != NULL && node->right != NULL) | |
| 201 | + return bbTreeNodeMax (node->right); | |
| 202 | + | |
| 203 | + return node; | |
| 204 | +} | |
| 205 | + | |
| 206 | +static | |
| 207 | + s_bbTreeNode * | |
| 208 | +bbTreeNodeMin (s_bbTreeNode * node) | |
| 209 | +{ | |
| 210 | + if (node != NULL && node->left != NULL) | |
| 211 | + return bbTreeNodeMin (node->left); | |
| 212 | + | |
| 213 | + return node; | |
| 214 | +} | |
| 215 | + | |
| 216 | +static | |
| 217 | + int | |
| 218 | +bbTreeNodeSize (s_bbTreeNode * node) | |
| 219 | +{ | |
| 220 | + int size = 0; | |
| 221 | + | |
| 222 | + if (node == NULL) | |
| 223 | + return 0; | |
| 224 | + | |
| 225 | + size += bbTreeNodeSize (node->left); | |
| 226 | + size += bbTreeNodeSize (node->right); | |
| 227 | + | |
| 228 | + return size + 1; | |
| 229 | +} | |
| 230 | +/* | |
| 231 | + * This functions removes nodes from the tree and returns a pointer | |
| 232 | + * to the removed node or NULL if no node was found. | |
| 233 | + * !!!FIXME!!!: This function isn't thread save because of the static | |
| 234 | + * valiables. Don't use with multiple threads. | |
| 235 | + */ | |
| 236 | +static | |
| 237 | + s_bbTreeNode * | |
| 238 | +bbTreeNodeRemove (s_bbTreeNode ** _node, t_bbTreeCmp cmp, void * value) | |
| 239 | +{ | |
| 240 | + s_bbTreeNode * ret = NULL; | |
| 241 | + s_bbTreeNode * node = *_node; | |
| 242 | + | |
| 243 | + if (node == NULL) | |
| 244 | + return NULL; | |
| 245 | + | |
| 246 | + if (cmp (value, node->value) == 0) | |
| 247 | + /* found the element left */ | |
| 248 | + { | |
| 249 | + if (node->left == NULL && node->right == NULL) | |
| 250 | + /* found a leaf */ | |
| 251 | + { | |
| 252 | + ret = bbTreeNodeNew (node->value); | |
| 253 | + free (node); | |
| 254 | + *_node = NULL; | |
| 255 | + } | |
| 256 | + else if (node->left != NULL && node->left != NULL) | |
| 257 | + /* left & right subtree exists use either max(left) or min(right) */ | |
| 258 | + { | |
| 259 | + s_bbTreeNode * maxLeft; | |
| 260 | + | |
| 261 | + maxLeft = bbTreeNodeMax (node->left); | |
| 262 | + node->value = maxLeft->value; | |
| 263 | + ret = bbTreeNodeRemove (&node->left, cmp, maxLeft->value); | |
| 264 | + | |
| 265 | + if (BBTREE_AVL (node) == -2 || BBTREE_AVL (node) == 2) | |
| 266 | + bbTreeNodeBalance (node); | |
| 267 | + | |
| 268 | + node->height = 1 + MAX ( | |
| 269 | + BBTREE_LEFT_HEIGHT (node), BBTREE_RIGHT_HEIGHT (node)); | |
| 270 | + } | |
| 271 | + else if ((node->left == NULL) != (node->right == NULL) /* ^^ */) | |
| 272 | + /* there is only one subtree */ | |
| 273 | + /* This subtree must be a leaf, because the tree is balanced */ | |
| 274 | + { | |
| 275 | + ret = bbTreeNodeNew (node->value); | |
| 276 | + | |
| 277 | + if (node->left != NULL) | |
| 278 | + /* found left node */ | |
| 279 | + { | |
| 280 | + node->value = node->left->value; | |
| 281 | + free (node->left); | |
| 282 | + node->left = NULL; | |
| 283 | + } | |
| 284 | + else | |
| 285 | + /* found right node */ | |
| 286 | + { | |
| 287 | + node->value = node->right->value; | |
| 288 | + free (node->right); | |
| 289 | + node->right = NULL; | |
| 290 | + } | |
| 291 | + } | |
| 292 | + | |
| 293 | + return ret; | |
| 294 | + } | |
| 295 | + | |
| 296 | + if (cmp (value, node->value) < 0) | |
| 297 | + ret = bbTreeNodeRemove (&node->left, cmp, value); | |
| 298 | + | |
| 299 | + if (cmp (value, node->value) > 0) | |
| 300 | + ret = bbTreeNodeRemove (&node->right, cmp, value); | |
| 301 | + | |
| 302 | + return ret; | |
| 303 | +} | |
| 304 | + | |
| 305 | +static | |
| 306 | + void | |
| 307 | +bbTreeNodeInOrder (const s_bbTreeNode * node, void *** ret) | |
| 308 | +{ | |
| 309 | + if (node != NULL && node->left != NULL) | |
| 310 | + bbTreeNodeInOrder (node->left, ret); | |
| 311 | + | |
| 312 | + if (node != NULL) | |
| 313 | + **ret = node->value; (*ret)++; | |
| 314 | + | |
| 315 | + if (node != NULL && node->right != NULL) | |
| 316 | + bbTreeNodeInOrder (node->right, ret); | |
| 317 | +} | |
| 318 | + | |
| 319 | +/* | |
| 320 | + * Interface (non-static functions) | |
| 321 | + */ | |
| 322 | + s_bbTree * | |
| 323 | +bbTreeNew (t_bbTreeCmp cmp) | |
| 324 | +{ | |
| 325 | + s_bbTree * new = (s_bbTree *) malloc (sizeof (s_bbTree)); | |
| 326 | + | |
| 327 | + new->root = NULL; | |
| 328 | + new->cmp = cmp; | |
| 329 | + | |
| 330 | + return new; | |
| 331 | +} | |
| 332 | + | |
| 333 | + void | |
| 334 | +bbTreeFree (s_bbTree * t) | |
| 335 | +{ | |
| 336 | + bbTreeNodeFree (t->root); | |
| 337 | + | |
| 338 | + free (t); | |
| 339 | +} | |
| 340 | + | |
| 341 | + void * | |
| 342 | +bbTreeInsert (s_bbTree * t, void * value) | |
| 343 | +{ | |
| 344 | + s_bbTreeNode * oldNode = bbTreeNodeInsert (&t->root, t->cmp, value); | |
| 345 | + | |
| 346 | + if (oldNode != NULL) | |
| 347 | + { | |
| 348 | + value = oldNode->value; | |
| 349 | + free (oldNode); | |
| 350 | + | |
| 351 | + return value; | |
| 352 | + } | |
| 353 | + | |
| 354 | + return NULL; | |
| 355 | +} | |
| 356 | + | |
| 357 | + void * | |
| 358 | +bbTreeSeek (s_bbTree * t, void * value) | |
| 359 | +{ | |
| 360 | + s_bbTreeNode * seek = bbTreeNodeSeek (t->root, t->cmp, value); | |
| 361 | + | |
| 362 | + return (seek != NULL) ? seek->value : NULL; | |
| 363 | +} | |
| 364 | + | |
| 365 | + void * | |
| 366 | +bbTreeRemove (s_bbTree * t, void * value) | |
| 367 | +{ | |
| 368 | + s_bbTreeNode * oldNode = bbTreeNodeRemove (&t->root, t->cmp, value); | |
| 369 | + | |
| 370 | + if (oldNode != NULL) | |
| 371 | + { | |
| 372 | + value = oldNode->value; | |
| 373 | + free (oldNode); | |
| 374 | + | |
| 375 | + return value; | |
| 376 | + } | |
| 377 | + | |
| 378 | + return NULL; | |
| 379 | +} | |
| 380 | + | |
| 381 | + void * | |
| 382 | +bbTreeMax (s_bbTree * t) | |
| 383 | +{ | |
| 384 | + s_bbTreeNode * max = bbTreeNodeMax (t->root); | |
| 385 | + | |
| 386 | + return max == NULL ? max : max->value; | |
| 387 | +} | |
| 388 | + | |
| 389 | + void * | |
| 390 | +bbTreeMin (s_bbTree * t) | |
| 391 | +{ | |
| 392 | + s_bbTreeNode * max = bbTreeNodeMin (t->root); | |
| 393 | + | |
| 394 | + return max == NULL ? max : max->value; | |
| 395 | +} | |
| 396 | + | |
| 397 | + int | |
| 398 | +bbTreeSize (s_bbTree * t) | |
| 399 | +{ | |
| 400 | + return bbTreeNodeSize (t->root); | |
| 401 | +} | |
| 402 | + | |
| 403 | + void ** | |
| 404 | +bbTreeInOrder (s_bbTree * t, void ** buffer) | |
| 405 | +{ | |
| 406 | + void ** tmp = buffer; | |
| 407 | + | |
| 408 | + bbTreeNodeInOrder (t->root, &tmp); | |
| 409 | + | |
| 410 | + return buffer; | |
| 411 | +} | ... | ... |
src/block.c
0 → 100644
| 1 | +#include <identList.h> | |
| 2 | +#include <stmtQueue.h> | |
| 3 | + | |
| 4 | +typedef struct block s_block; | |
| 5 | + | |
| 6 | +struct block /* a stack of used blocks. */ | |
| 7 | +{ | |
| 8 | + s_stmtQueue * stmts; | |
| 9 | + s_identList * idl; | |
| 10 | + | |
| 11 | + s_block * prev; | |
| 12 | +}; | |
| 13 | + | |
| 14 | + | |
| 15 | + s_block * | |
| 16 | +blockNew (s_stmtQueue * stmts) | |
| 17 | +{ | |
| 18 | + s_block * new = (s_block *) malloc (sizeof (s_block)); | |
| 19 | + | |
| 20 | + new->stmts = stmts; | |
| 21 | + new->prev = NULL; | |
| 22 | + new->idl = identListNew (new); | |
| 23 | + | |
| 24 | + return new; | |
| 25 | +} | |
| 26 | + | |
| 27 | + void | |
| 28 | +blockFree (s_block * bs) | |
| 29 | +{ | |
| 30 | + if (bs->prev != NULL) | |
| 31 | + blockFree (bs->prev); | |
| 32 | + | |
| 33 | + if (bs->stmts != NULL) | |
| 34 | + stmtQueueFree (bs->stmts); | |
| 35 | + | |
| 36 | + identListFree (bs->idl); | |
| 37 | + | |
| 38 | + free (bs); | |
| 39 | +} | |
| 40 | + | |
| 41 | + void | |
| 42 | +blockSetNonLocalId (s_block * bs, s_ident * id) | |
| 43 | +{ | |
| 44 | + s_identListPutVal (bs->idl, id); | |
| 45 | +} | |
| 46 | + | |
| 47 | + s_block * | |
| 48 | +blockPush (s_block ** bs, s_block * new) | |
| 49 | +{ | |
| 50 | + new->prev = *bs; | |
| 51 | + | |
| 52 | + *bs = new; | |
| 53 | + | |
| 54 | + return *bs; | |
| 55 | +} | |
| 56 | + | |
| 57 | + s_block * | |
| 58 | +blockPop (s_block ** bs) | |
| 59 | +{ | |
| 60 | + s_block * ret = *bs; | |
| 61 | + *bs = (*bs)->prev; | |
| 62 | + | |
| 63 | + return ret; | |
| 64 | +} | |
| 65 | + | |
| 66 | + s_block * | |
| 67 | +blockPrev (s_block * bs) | |
| 68 | +{ | |
| 69 | + return bs->prev; | |
| 70 | +} | |
| 71 | + | |
| 72 | + s_stmtQueue * | |
| 73 | +blockStmts (s_block * bs) | |
| 74 | +{ | |
| 75 | + return bs->stmts; | |
| 76 | +} | |
| 77 | + | |
| 78 | + s_identList * | |
| 79 | +blockIdl (s_block * bs) | |
| 80 | +{ | |
| 81 | + return bs->idl; | |
| 82 | +} | ... | ... |
src/cast.c
0 → 100644
| 1 | +#include <stdio.h> | |
| 2 | +#include <stdlib.h> | |
| 3 | +#include <malloc.h> | |
| 4 | +#include <string.h> | |
| 5 | + | |
| 6 | +#include <expValue.h> | |
| 7 | +#include <cast.h> | |
| 8 | + | |
| 9 | + s_expVal * | |
| 10 | +castExprToInt (s_expVal * eVal) | |
| 11 | +{ | |
| 12 | + return expValueIntNew (expValueInt (eVal)); | |
| 13 | +} | |
| 14 | + | |
| 15 | + s_expVal * | |
| 16 | +castExprToFloat (s_expVal * eVal) | |
| 17 | +{ | |
| 18 | + return expValueFloatNew (expValueFloat (eVal)); | |
| 19 | +} | |
| 20 | + | |
| 21 | + s_expVal * | |
| 22 | +castExprToString (s_expVal * eVal) | |
| 23 | +{ | |
| 24 | + char * val = expValueString (eVal); | |
| 25 | + s_expVal * ret = expValueStringNew (val); | |
| 26 | + | |
| 27 | + free (val); | |
| 28 | + | |
| 29 | + return ret; | |
| 30 | +} | ... | ... |
src/evalCond.c
0 → 100644
| 1 | +#include <string.h> | |
| 2 | +#include <stdlib.h> | |
| 3 | +#include <stdio.h> | |
| 4 | + | |
| 5 | +#include <expValue.h> | |
| 6 | +#include <tepal_pars.h> | |
| 7 | +#include <evalCond.h> | |
| 8 | + | |
| 9 | + | |
| 10 | +/* | |
| 11 | + * static function (internal only) | |
| 12 | + */ | |
| 13 | +static | |
| 14 | + int | |
| 15 | +evalIntComp (int op, s_expVal * _op1, s_expVal * _op2) | |
| 16 | +{ | |
| 17 | + long op1 = expValueInt (_op1); | |
| 18 | + long op2 = expValueInt (_op2); | |
| 19 | + | |
| 20 | + switch (op) | |
| 21 | + { | |
| 22 | + case EQ: return (op1 == op2); | |
| 23 | + case NE: return (op1 != op2); | |
| 24 | + case LT: return (op1 < op2); | |
| 25 | + case GT: return (op1 > op2); | |
| 26 | + case LE: return (op1 <= op2); | |
| 27 | + case GE: return (op1 >= op2); | |
| 28 | + } | |
| 29 | +} | |
| 30 | + | |
| 31 | +static | |
| 32 | + int | |
| 33 | +evalFloatComp (int op, s_expVal * _op1, s_expVal * _op2) | |
| 34 | +{ | |
| 35 | + double op1 = expValueFloat (_op1); | |
| 36 | + double op2 = expValueFloat (_op2); | |
| 37 | + | |
| 38 | + switch (op) | |
| 39 | + { | |
| 40 | + case EQ: return (op1 == op2); | |
| 41 | + case NE: return (op1 != op2); | |
| 42 | + case LT: return (op1 < op2); | |
| 43 | + case GT: return (op1 > op2); | |
| 44 | + case LE: return (op1 <= op2); | |
| 45 | + case GE: return (op1 >= op2); | |
| 46 | + } | |
| 47 | +} | |
| 48 | + | |
| 49 | +static | |
| 50 | + int | |
| 51 | +evalStringComp (int op, s_expVal * _op1, s_expVal * _op2) | |
| 52 | +{ | |
| 53 | + char * op1 = expValueString (_op1); | |
| 54 | + char * op2 = expValueString (_op2); | |
| 55 | + long ret; | |
| 56 | + | |
| 57 | + switch (op) | |
| 58 | + { | |
| 59 | + case EQ: ret = (! strcmp (op1, op2)); | |
| 60 | + case NE: ret = strcmp (op1, op2); | |
| 61 | + case LT: ret = (strcmp (op1, op2) < 0) ? 1 : 0; | |
| 62 | + case GT: ret = (strcmp (op1, op2) > 0) ? 1 : 0; | |
| 63 | + case LE: ret = (strcmp (op1, op2) <= 0) ? 1 : 0; | |
| 64 | + case GE: ret = (strcmp (op1, op2) >= 0) ? 1 : 0; | |
| 65 | + } | |
| 66 | + | |
| 67 | + free (op1); | |
| 68 | + free (op2); | |
| 69 | + | |
| 70 | + return ret; | |
| 71 | +} | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | +/* | |
| 76 | + * public functions (interface) | |
| 77 | + */ | |
| 78 | + int | |
| 79 | +evalCondExpr (s_expVal * _op) | |
| 80 | +{ | |
| 81 | + switch (expValueGetType (_op)) | |
| 82 | + { | |
| 83 | + case EXP_TYP_INT: return expValueInt (_op); | |
| 84 | + case EXP_TYP_FLOAT: return expValueInt (_op); | |
| 85 | + case EXP_TYP_STRING: | |
| 86 | + { | |
| 87 | + char * op = expValueString (_op); | |
| 88 | + long ret = strlen (op); | |
| 89 | + | |
| 90 | + free (op); | |
| 91 | + | |
| 92 | + return ret; | |
| 93 | + } | |
| 94 | + } | |
| 95 | + | |
| 96 | + return 0; | |
| 97 | +} | |
| 98 | + | |
| 99 | + int | |
| 100 | +evalComp (int op, s_expVal * op1, s_expVal * op2) | |
| 101 | +{ | |
| 102 | + switch (expValueGetType (op1)) | |
| 103 | + { | |
| 104 | + case EXP_TYP_INT: | |
| 105 | + return evalIntComp (op, op1, op2); | |
| 106 | + | |
| 107 | + case EXP_TYP_FLOAT: | |
| 108 | + return evalFloatComp (op, op1, op2); | |
| 109 | + | |
| 110 | + case EXP_TYP_STRING: | |
| 111 | + return evalStringComp (op, op1, op2); | |
| 112 | + } | |
| 113 | +} | ... | ... |
src/evalExpr.c
0 → 100644
| 1 | +#include <malloc.h> | |
| 2 | +#include <string.h> | |
| 3 | +#include <stdlib.h> | |
| 4 | +#include <stdio.h> | |
| 5 | + | |
| 6 | +#include <expValue.h> | |
| 7 | +#include <tepal.h> | |
| 8 | +#include <tepal_pars.h> | |
| 9 | +#include <evalExpr.h> | |
| 10 | + | |
| 11 | + | |
| 12 | +/* | |
| 13 | + * static function (internal only) | |
| 14 | + */ | |
| 15 | +static | |
| 16 | +inline | |
| 17 | + s_expVal * | |
| 18 | +stringPlus (s_expVal * _op1, s_expVal * _op2) | |
| 19 | +{ | |
| 20 | + s_expVal * ret; | |
| 21 | + char * op1 = expValueString (_op1); | |
| 22 | + char * op2 = expValueString (_op2); | |
| 23 | + char * retVal = (char *) malloc ( | |
| 24 | + sizeof (char) * (strlen (op1) + strlen (op2) + 1)); | |
| 25 | + | |
| 26 | + strcpy (retVal, op1); | |
| 27 | + strcat (retVal, op2); | |
| 28 | + ret = expValueStringNew (retVal); | |
| 29 | + | |
| 30 | + free (retVal); | |
| 31 | + free (op2); | |
| 32 | + free (op1); | |
| 33 | + | |
| 34 | + return ret; | |
| 35 | +} | |
| 36 | + | |
| 37 | +static | |
| 38 | +inline | |
| 39 | + s_expVal * | |
| 40 | +stringNeg (s_expVal * _op) | |
| 41 | +{ | |
| 42 | + s_expVal * ret; | |
| 43 | + int i; | |
| 44 | + | |
| 45 | + char * op = expValueString (_op); | |
| 46 | + int len = strlen (op) - 1; | |
| 47 | + | |
| 48 | + for (i=0; i<=(len/2); i++) | |
| 49 | + { | |
| 50 | + char tmp = op[i]; | |
| 51 | + op[i] = op[len-i]; | |
| 52 | + op[len-i] = tmp; | |
| 53 | + } | |
| 54 | + | |
| 55 | + ret = expValueStringNew (op); | |
| 56 | + free (op); | |
| 57 | + return ret; | |
| 58 | +} | |
| 59 | + | |
| 60 | +static | |
| 61 | +inline | |
| 62 | + s_expVal * | |
| 63 | +evalIntExp (int op, s_expVal * _op1, s_expVal * _op2) | |
| 64 | +{ | |
| 65 | + long op1 = expValueInt (_op1); | |
| 66 | + long op2 = (_op2 != NULL) ? expValueInt (_op2) : 0; | |
| 67 | + | |
| 68 | + if (op == NEG) return expValueIntNew (- op1); | |
| 69 | + | |
| 70 | + switch (expValueGetType (_op2)) | |
| 71 | + { | |
| 72 | + case EXP_TYP_INT: | |
| 73 | + case EXP_TYP_FLOAT: | |
| 74 | + switch (op) | |
| 75 | + { | |
| 76 | + case PLUS: return expValueIntNew (op1 + op2); | |
| 77 | + case MINUS: return expValueIntNew (op1 - op2); | |
| 78 | + case TIMES: return expValueIntNew (op1 * op2); | |
| 79 | + case OVER: return expValueIntNew (op1 / op2); | |
| 80 | + case MODULO: return expValueIntNew (op1 % op2); | |
| 81 | + } | |
| 82 | + | |
| 83 | + case EXP_TYP_STRING: | |
| 84 | + if (op == PLUS) | |
| 85 | + return stringPlus (_op1, _op2); | |
| 86 | + exitError (ERR_STRING_OPERATOR, op); | |
| 87 | + } | |
| 88 | +} | |
| 89 | + | |
| 90 | +static | |
| 91 | +inline | |
| 92 | + s_expVal * | |
| 93 | +evalFloatExp (int op, s_expVal * _op1, s_expVal * _op2) | |
| 94 | +{ | |
| 95 | + double op1 = expValueFloat (_op1); | |
| 96 | + double op2 = (_op2 != NULL) ? expValueFloat (_op2) : 0.0; | |
| 97 | + | |
| 98 | + if (op == NEG) return expValueFloatNew (- op1); | |
| 99 | + | |
| 100 | + switch (expValueGetType (_op2)) | |
| 101 | + { | |
| 102 | + case EXP_TYP_INT: | |
| 103 | + case EXP_TYP_FLOAT: | |
| 104 | + switch (op) | |
| 105 | + { | |
| 106 | + case MODULO: exitError (ERR_FLOAT_OPERATOR, op); | |
| 107 | + case PLUS: return expValueFloatNew (op1 + op2); | |
| 108 | + case MINUS: return expValueFloatNew (op1 - op2); | |
| 109 | + case TIMES: return expValueFloatNew (op1 * op2); | |
| 110 | + case OVER: return expValueFloatNew (op1 / op2); | |
| 111 | + } | |
| 112 | + | |
| 113 | + case EXP_TYP_STRING: | |
| 114 | + if (op == PLUS) | |
| 115 | + return stringPlus (_op1, _op2); | |
| 116 | + exitError (ERR_STRING_OPERATOR, op); | |
| 117 | + } | |
| 118 | +} | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | +/* | |
| 123 | + * public functions (interface) | |
| 124 | + */ | |
| 125 | + s_expVal * | |
| 126 | +evalExpr (int op, s_expVal * op1, s_expVal * op2) | |
| 127 | +{ | |
| 128 | + switch (expValueGetType (op1)) | |
| 129 | + { | |
| 130 | + case EXP_TYP_INT: | |
| 131 | + return evalIntExp (op, op1, op2); | |
| 132 | + | |
| 133 | + case EXP_TYP_FLOAT: | |
| 134 | + if (op != MODULO) | |
| 135 | + return evalFloatExp (op, op1, op2); | |
| 136 | + exitError (ERR_FLOAT_OPERATOR, op); | |
| 137 | + | |
| 138 | + case EXP_TYP_STRING: | |
| 139 | + if (op == PLUS) | |
| 140 | + return stringPlus (op1, op2); | |
| 141 | + if (op == NEG) | |
| 142 | + return stringNeg (op1); | |
| 143 | + exitError (ERR_STRING_OPERATOR, op); | |
| 144 | + } | |
| 145 | +} | ... | ... |
src/expValue.c
0 → 100644
| 1 | +#include <string.h> | |
| 2 | +#include <malloc.h> | |
| 3 | +#include <stdio.h> | |
| 4 | + | |
| 5 | +#include <expValue.h> | |
| 6 | + | |
| 7 | +union expType | |
| 8 | +{ | |
| 9 | + long iVal; | |
| 10 | + double fVal; | |
| 11 | + char * cPtr; | |
| 12 | +}; | |
| 13 | + | |
| 14 | +struct expVal | |
| 15 | +{ | |
| 16 | + int type; | |
| 17 | + | |
| 18 | + union expType val; | |
| 19 | +}; | |
| 20 | + | |
| 21 | +/* | |
| 22 | + * Constructoren / Destructoren | |
| 23 | + */ | |
| 24 | + s_expVal * | |
| 25 | +expValueIntNew (long val) | |
| 26 | +{ | |
| 27 | + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal)); | |
| 28 | + | |
| 29 | + ret->type = EXP_TYP_INT; | |
| 30 | + ret->val.iVal = val; | |
| 31 | + | |
| 32 | + return ret; | |
| 33 | +} | |
| 34 | + | |
| 35 | + s_expVal * | |
| 36 | +expValueFloatNew (double val) | |
| 37 | +{ | |
| 38 | + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal)); | |
| 39 | + | |
| 40 | + ret->type = EXP_TYP_FLOAT; | |
| 41 | + ret->val.fVal = val; | |
| 42 | + | |
| 43 | + return ret; | |
| 44 | +} | |
| 45 | + | |
| 46 | + s_expVal * | |
| 47 | +expValueStringNew (char * val) | |
| 48 | +{ | |
| 49 | + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal)); | |
| 50 | + | |
| 51 | + ret->type = EXP_TYP_STRING; | |
| 52 | + ret->val.cPtr = (char *) malloc (sizeof (char) * (strlen (val) + 1)); | |
| 53 | + strcpy (ret->val.cPtr, val); | |
| 54 | + | |
| 55 | + return ret; | |
| 56 | +} | |
| 57 | + | |
| 58 | + s_expVal * | |
| 59 | +expValueClone (s_expVal * eVal) | |
| 60 | +{ | |
| 61 | + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal)); | |
| 62 | + | |
| 63 | + ret->type = eVal->type; | |
| 64 | + | |
| 65 | + switch (eVal->type) | |
| 66 | + { | |
| 67 | + case EXP_TYP_INT: ret->val.iVal = eVal->val.iVal; break; | |
| 68 | + case EXP_TYP_FLOAT: ret->val.fVal = eVal->val.fVal; break; | |
| 69 | + case EXP_TYP_STRING: | |
| 70 | + { | |
| 71 | + ret->val.cPtr = (char *) malloc ( | |
| 72 | + sizeof (char) * (strlen (eVal->val.cPtr) + 1)); | |
| 73 | + strcpy (ret->val.cPtr, eVal->val.cPtr); | |
| 74 | + } | |
| 75 | + } | |
| 76 | + | |
| 77 | + return ret; | |
| 78 | +} | |
| 79 | + | |
| 80 | + void | |
| 81 | +expValueFree (s_expVal * eVal) | |
| 82 | +{ | |
| 83 | + if (eVal->type == EXP_TYP_STRING) | |
| 84 | + free (eVal->val.cPtr); | |
| 85 | + free (eVal); | |
| 86 | +} | |
| 87 | + | |
| 88 | + | |
| 89 | +/* | |
| 90 | + * Accessors | |
| 91 | + */ | |
| 92 | + long | |
| 93 | +expValueInt (s_expVal * eVal) | |
| 94 | +{ | |
| 95 | + switch (eVal->type) | |
| 96 | + { | |
| 97 | + case EXP_TYP_INT: return eVal->val.iVal; | |
| 98 | + case EXP_TYP_FLOAT: return (long) eVal->val.fVal; | |
| 99 | + case EXP_TYP_STRING: return atoi (eVal->val.cPtr); | |
| 100 | + } | |
| 101 | +} | |
| 102 | + | |
| 103 | + double | |
| 104 | +expValueFloat (s_expVal * eVal) | |
| 105 | +{ | |
| 106 | + switch (eVal->type) | |
| 107 | + { | |
| 108 | + case EXP_TYP_INT: return (double) eVal->val.iVal; | |
| 109 | + case EXP_TYP_FLOAT: return eVal->val.fVal; | |
| 110 | + case EXP_TYP_STRING: return atof (eVal->val.cPtr); | |
| 111 | + } | |
| 112 | +} | |
| 113 | + | |
| 114 | + char * | |
| 115 | +expValueString (s_expVal * eVal) | |
| 116 | +{ | |
| 117 | + char buf[40]; | |
| 118 | + char * ret = NULL; | |
| 119 | + | |
| 120 | + switch (eVal->type) | |
| 121 | + { | |
| 122 | + case EXP_TYP_INT: | |
| 123 | + sprintf (buf, "%d", eVal->val.iVal); | |
| 124 | + ret = (char *) malloc (sizeof (char) * (strlen (buf) + 1)); | |
| 125 | + strcpy (ret, buf); | |
| 126 | + break; | |
| 127 | + | |
| 128 | + case EXP_TYP_FLOAT: | |
| 129 | + sprintf (buf, "%f", eVal->val.fVal); | |
| 130 | + ret = (char *) malloc (sizeof (char) * (strlen (buf) + 1)); | |
| 131 | + strcpy (ret, buf); | |
| 132 | + break; | |
| 133 | + | |
| 134 | + case EXP_TYP_STRING: | |
| 135 | + ret = (char *) malloc (sizeof (char) * (strlen (eVal->val.cPtr) + 1)); | |
| 136 | + strcpy (ret, eVal->val.cPtr); | |
| 137 | + break; | |
| 138 | + } | |
| 139 | + | |
| 140 | + return ret; | |
| 141 | +} | |
| 142 | + | |
| 143 | +/* | |
| 144 | + * analyse expValue | |
| 145 | + */ | |
| 146 | + int | |
| 147 | +expValueGetType (s_expVal * eVal) | |
| 148 | +{ | |
| 149 | + return eVal->type; | |
| 150 | +} | ... | ... |
src/ident.c
0 → 100644
| 1 | +#include <string.h> | |
| 2 | +#include <malloc.h> | |
| 3 | +#include <stdio.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | + | |
| 6 | +#include <expValue.h> | |
| 7 | +#include <identList.h> | |
| 8 | +#include <tepal.h> | |
| 9 | +#include <ident.h> | |
| 10 | + | |
| 11 | + | |
| 12 | +/* | |
| 13 | + * Typdeklaration, etc | |
| 14 | + */ | |
| 15 | +union identTypes | |
| 16 | +{ | |
| 17 | + s_expVal * base; | |
| 18 | + s_identList * idl; | |
| 19 | +}; | |
| 20 | + | |
| 21 | +struct ident | |
| 22 | +{ | |
| 23 | + char * key; | |
| 24 | + int idx; | |
| 25 | + | |
| 26 | + int queued; | |
| 27 | + | |
| 28 | + union identTypes val; | |
| 29 | +}; | |
| 30 | + | |
| 31 | + | |
| 32 | +/* | |
| 33 | + * statische Funktionen (interner gebrauch) | |
| 34 | + */ | |
| 35 | + | |
| 36 | +/* | |
| 37 | + * nicht statische Funktionen (Interface) | |
| 38 | + */ | |
| 39 | + | |
| 40 | +/* | |
| 41 | + * Contructors / Destructors for ident | |
| 42 | + */ | |
| 43 | + s_ident * | |
| 44 | +identNew (int idx, const char * key) | |
| 45 | +{ | |
| 46 | + int keyLen = (key == NULL) ? 2 : 2 + strlen (key); | |
| 47 | + s_ident * ident = (s_ident *) malloc (sizeof (s_ident)); | |
| 48 | + | |
| 49 | + ident->idx = idx; | |
| 50 | + ident->key = (char *) malloc (sizeof (char) * keyLen); | |
| 51 | + | |
| 52 | + ident->key[0] = ID_TYP_UNDEF; | |
| 53 | + ident->key[1] = '\0'; | |
| 54 | + | |
| 55 | + if (key != NULL) | |
| 56 | + strcpy (ident->key + 1, key); | |
| 57 | + | |
| 58 | + ident->queued = 0; | |
| 59 | + | |
| 60 | + return ident; | |
| 61 | +} | |
| 62 | + | |
| 63 | + s_ident * | |
| 64 | +identUndefNew (int idx, const char * key) | |
| 65 | +{ | |
| 66 | +#ifdef DEBUG2 | |
| 67 | + printf ("[!DEBUG!] identUndefNew: %d/%s\n", idx, key); | |
| 68 | +#endif | |
| 69 | + | |
| 70 | + return identNew (idx, key); | |
| 71 | +} | |
| 72 | + | |
| 73 | + s_ident * | |
| 74 | +identExpNew (int idx, const char * key, s_expVal * val) | |
| 75 | +{ | |
| 76 | + s_ident * ident = identNew (idx, key); | |
| 77 | + | |
| 78 | +#ifdef DEBUG2 | |
| 79 | + printf ("[!DEBUG!] identExpNew: %d/%s\n", idx, key); | |
| 80 | +#endif | |
| 81 | + | |
| 82 | + ident->key[0] = ID_TYP_EXP; | |
| 83 | + ident->val.base = expValueClone (val); | |
| 84 | + | |
| 85 | + return ident; | |
| 86 | +} | |
| 87 | + | |
| 88 | + s_ident * | |
| 89 | +identIdlNew (int idx, const char * key, s_identList * val) | |
| 90 | +{ | |
| 91 | + s_ident * ident = identNew (idx, key); | |
| 92 | + | |
| 93 | +#ifdef DEBUG2 | |
| 94 | + printf ("[!DEBUG!] identIdlNew: %d/%s\n", idx, key); | |
| 95 | +#endif | |
| 96 | + | |
| 97 | + ident->key[0] = ID_TYP_IDL; | |
| 98 | + ident->val.idl = val; | |
| 99 | + | |
| 100 | + return ident; | |
| 101 | +} | |
| 102 | + | |
| 103 | + void | |
| 104 | +identFree (s_ident * id) | |
| 105 | +{ | |
| 106 | +#ifdef DEBUG2 | |
| 107 | + printf ("[!DEBUG!] identFree: %d/%s\n", id->idx, id->key); | |
| 108 | +#endif | |
| 109 | + | |
| 110 | + switch (identGetType (id)) | |
| 111 | + { | |
| 112 | + case ID_TYP_EXP: expValueFree (id->val.base); break; | |
| 113 | + case ID_TYP_IDL: identListFree (id->val.idl); break; | |
| 114 | + } | |
| 115 | + | |
| 116 | + free (id->key); | |
| 117 | + free (id); | |
| 118 | +} | |
| 119 | + | |
| 120 | +/* | |
| 121 | + * analyse ident | |
| 122 | + */ | |
| 123 | + int | |
| 124 | +identIsQueued (s_ident * id) | |
| 125 | +{ | |
| 126 | + return id->queued; | |
| 127 | +} | |
| 128 | + | |
| 129 | + void | |
| 130 | +identEnqueue (s_ident * id) | |
| 131 | +{ | |
| 132 | + id->queued ++; | |
| 133 | +} | |
| 134 | + | |
| 135 | + void | |
| 136 | +identDequeue (s_ident * id) | |
| 137 | +{ | |
| 138 | + id->queued --; | |
| 139 | +} | |
| 140 | + | |
| 141 | + int | |
| 142 | +identGetType (s_ident * id) | |
| 143 | +{ | |
| 144 | + return id->key[0]; | |
| 145 | +} | |
| 146 | + | |
| 147 | + char * | |
| 148 | +identGetKey (s_ident * id) | |
| 149 | +{ | |
| 150 | + return id->key + 1; | |
| 151 | +} | |
| 152 | + | |
| 153 | + int | |
| 154 | +identGetIdx (s_ident * id) | |
| 155 | +{ | |
| 156 | + return id->idx; | |
| 157 | +} | |
| 158 | + | |
| 159 | +/* identifier to value */ | |
| 160 | + s_expVal * | |
| 161 | +identExp (s_ident * id) | |
| 162 | +{ | |
| 163 | + s_expVal * ret = NULL; | |
| 164 | + | |
| 165 | + if (id == NULL) | |
| 166 | + exitError (ERR_UNDEF_VAR, identGetKey (id)); | |
| 167 | + | |
| 168 | + if (identGetType (id) == ID_TYP_EXP) | |
| 169 | + { | |
| 170 | + ret = expValueClone (id->val.base); | |
| 171 | + } | |
| 172 | + | |
| 173 | + return ret; | |
| 174 | +} | |
| 175 | + | |
| 176 | + s_identList * | |
| 177 | +identIdl (s_ident * id) | |
| 178 | +{ | |
| 179 | + s_identList * ret = NULL; | |
| 180 | + | |
| 181 | + if (identGetType (id) == ID_TYP_IDL) | |
| 182 | + { | |
| 183 | + ret = id->val.idl; | |
| 184 | + } | |
| 185 | + | |
| 186 | + return ret; | |
| 187 | +} | |
| 188 | + | |
| 189 | + s_ident * | |
| 190 | +identSetExp (s_ident * id, s_expVal * val) | |
| 191 | +{ | |
| 192 | + switch (identGetType (id)) | |
| 193 | + { | |
| 194 | + case ID_TYP_EXP: expValueFree (id->val.base); break; | |
| 195 | + case ID_TYP_IDL: identListFree (id->val.idl); break; | |
| 196 | + } | |
| 197 | + | |
| 198 | + id->key[0] = ID_TYP_EXP; | |
| 199 | + id->val.base = expValueClone (val); | |
| 200 | + | |
| 201 | + return id; | |
| 202 | +} | |
| 203 | + | |
| 204 | + s_ident * | |
| 205 | +identSetIdl (s_ident * id, s_identList * val) | |
| 206 | +{ | |
| 207 | + switch (identGetType (id)) | |
| 208 | + { | |
| 209 | + case ID_TYP_EXP: expValueFree (id->val.base); | |
| 210 | + case ID_TYP_IDL: identListFree (id->val.idl); | |
| 211 | + } | |
| 212 | + | |
| 213 | + id->key[0] = ID_TYP_IDL; | |
| 214 | + id->val.idl = val; | |
| 215 | + | |
| 216 | + return id; | |
| 217 | +} | ... | ... |
src/identList.c
0 → 100644
| 1 | +#include <string.h> | |
| 2 | +#include <malloc.h> | |
| 3 | +#include <stdio.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | + | |
| 6 | +#include <expValue.h> | |
| 7 | +#include <bbtree.h> | |
| 8 | +#include <ident.h> | |
| 9 | +#include <identList.h> | |
| 10 | + | |
| 11 | + | |
| 12 | +struct identList | |
| 13 | +{ | |
| 14 | + s_bbTree * idIdx; | |
| 15 | + s_bbTree * idHash; | |
| 16 | +}; | |
| 17 | + | |
| 18 | + | |
| 19 | +/* | |
| 20 | + * statische Funktionen (interner gebrauch) | |
| 21 | + */ | |
| 22 | +static | |
| 23 | + int | |
| 24 | +idHashCmp (void * _a, void * _b) | |
| 25 | +{ | |
| 26 | + s_ident * a = (s_ident *) _a; | |
| 27 | + s_ident * b = (s_ident *) _b; | |
| 28 | + | |
| 29 | + return strcmp (identGetKey (a), identGetKey (b)); | |
| 30 | +} | |
| 31 | + | |
| 32 | +static | |
| 33 | + int | |
| 34 | +idIdxCmp (void * _a, void * _b) | |
| 35 | +{ | |
| 36 | + s_ident * a = (s_ident *) _a; | |
| 37 | + s_ident * b = (s_ident *) _b; | |
| 38 | + | |
| 39 | + return identGetIdx (a) - identGetIdx (b); | |
| 40 | +} | |
| 41 | + | |
| 42 | + | |
| 43 | +/* | |
| 44 | + * nicht statische Funktionen (Interface) | |
| 45 | + */ | |
| 46 | + | |
| 47 | +/* | |
| 48 | + * Contructors / Destructors for identList | |
| 49 | + */ | |
| 50 | + s_identList * | |
| 51 | +identListNew (void) | |
| 52 | +{ | |
| 53 | + s_identList * ret = (s_identList *) malloc (sizeof (s_identList)); | |
| 54 | + | |
| 55 | + ret->idIdx = bbTreeNew (idIdxCmp); | |
| 56 | + ret->idHash = bbTreeNew (idHashCmp); | |
| 57 | + | |
| 58 | + return ret; | |
| 59 | +} | |
| 60 | + | |
| 61 | +void | |
| 62 | +identListFree (s_identList * l) | |
| 63 | +{ | |
| 64 | + s_ident ** idArray, | |
| 65 | + ** _run; | |
| 66 | + | |
| 67 | + for (_run = idArray = (s_ident **) identListToArray (l); | |
| 68 | + *_run != NULL; | |
| 69 | + _run++) | |
| 70 | + { | |
| 71 | + identDequeue (*_run); | |
| 72 | + if (! identIsQueued (*_run)) | |
| 73 | + identFree (*_run); | |
| 74 | + } | |
| 75 | + | |
| 76 | + free (idArray); | |
| 77 | + | |
| 78 | + bbTreeFree (l->idIdx); | |
| 79 | + bbTreeFree (l->idHash); | |
| 80 | + | |
| 81 | + free (l); | |
| 82 | +} | |
| 83 | + | |
| 84 | +/* | |
| 85 | + * insertions or deletion into a identList | |
| 86 | + */ | |
| 87 | + s_ident * | |
| 88 | +identListPutVal (s_identList * l, s_ident * val) | |
| 89 | +{ | |
| 90 | + s_ident * oldVal; | |
| 91 | + int idx = identGetIdx (val); | |
| 92 | + char * key = identGetKey (val); | |
| 93 | + | |
| 94 | + identEnqueue (val); | |
| 95 | + | |
| 96 | + if ((idx < 0 && key[0] == '\0') || idx != -1 && key[0] != '\0') | |
| 97 | + /* calling error: either key or idx must be valid. But not both. */ | |
| 98 | + return NULL; | |
| 99 | + | |
| 100 | + if (idx >= 0) | |
| 101 | + oldVal = (s_ident *) bbTreeInsert (l->idIdx, val); | |
| 102 | + else | |
| 103 | + oldVal = (s_ident *) bbTreeInsert (l->idHash, val); | |
| 104 | + | |
| 105 | + if (oldVal != NULL) | |
| 106 | + /* | |
| 107 | + * these are few lines with a lot behind them. The not obvious question | |
| 108 | + * here is: What happens if oldval points to the same address than val? | |
| 109 | + * well, this could only happen if val was was formally queued, because | |
| 110 | + * else oldVal would be NULL. Knowing this makes clear that the queue | |
| 111 | + * state is not changed at all, because first it was increased above with | |
| 112 | + * identEnqueue and the it will be decreased in this if block again. But as | |
| 113 | + * it was formally queued it will not be freed (Good)! | |
| 114 | + */ | |
| 115 | + { | |
| 116 | + identDequeue (oldVal); | |
| 117 | + if (! identIsQueued (oldVal)) | |
| 118 | + identFree (oldVal); | |
| 119 | + } | |
| 120 | + | |
| 121 | + return val; | |
| 122 | +} | |
| 123 | + | |
| 124 | + s_ident * | |
| 125 | +identListPutExpByIdx (s_identList * l, int idx, s_expVal * val) | |
| 126 | +{ | |
| 127 | + return identListPutVal (l, identExpNew (idx, NULL, val)); | |
| 128 | +} | |
| 129 | + | |
| 130 | + s_ident * | |
| 131 | +identListPutIdlByIdx (s_identList * l, int idx, s_identList * val) | |
| 132 | +{ | |
| 133 | + return identListPutVal (l, identIdlNew (idx, NULL, val)); | |
| 134 | +} | |
| 135 | + | |
| 136 | + s_ident * | |
| 137 | +identListPutExpByKey (s_identList * l, const char * key, s_expVal * val) | |
| 138 | +{ | |
| 139 | + return identListPutVal (l, identExpNew (-1, key, val)); | |
| 140 | +} | |
| 141 | + | |
| 142 | + s_ident * | |
| 143 | +identListPutIdlByKey (s_identList * l, const char * key, s_identList * val) | |
| 144 | +{ | |
| 145 | + return identListPutVal (l, identIdlNew (-1, key, val)); | |
| 146 | +} | |
| 147 | + | |
| 148 | + void | |
| 149 | +identListRemoveByIdx (s_identList * l, int idx) | |
| 150 | +{ | |
| 151 | + s_ident * seek = (s_ident *) identNew (idx, NULL); | |
| 152 | + s_ident * val = bbTreeRemove (l->idIdx, seek); | |
| 153 | + | |
| 154 | +#ifdef DEBUG2 | |
| 155 | + printf ("[!DEBUG!] seek (remove) identNew: %d/%s\n", idx, ""); | |
| 156 | +#endif | |
| 157 | + | |
| 158 | + identFree (seek); | |
| 159 | + | |
| 160 | + if (val != NULL) | |
| 161 | + { | |
| 162 | + identDequeue (val); | |
| 163 | + if (! identIsQueued (val)) | |
| 164 | + identFree (val); | |
| 165 | + } | |
| 166 | +} | |
| 167 | + | |
| 168 | + void | |
| 169 | +identListRemoveByKey (s_identList * l, const char * key) | |
| 170 | +{ | |
| 171 | + s_ident * seek = (s_ident *) identNew (-1, key); | |
| 172 | + s_ident * val = bbTreeRemove (l->idIdx, seek); | |
| 173 | + | |
| 174 | +#ifdef DEBUG2 | |
| 175 | + printf ("[!DEBUG!] seek (remove) identNew: %d/%s\n", -1, key); | |
| 176 | +#endif | |
| 177 | + | |
| 178 | + identFree (seek); | |
| 179 | + | |
| 180 | + if (val != NULL) | |
| 181 | + { | |
| 182 | + identDequeue (val); | |
| 183 | + if (! identIsQueued (val)) | |
| 184 | + identFree (val); | |
| 185 | + } | |
| 186 | +} | |
| 187 | + | |
| 188 | +/* | |
| 189 | + * seeking in identList | |
| 190 | + */ | |
| 191 | + s_ident * | |
| 192 | +identListSeekIdx (s_identList * l, int idx) | |
| 193 | +{ | |
| 194 | + s_ident * seek = (s_ident *) identNew (idx, NULL); | |
| 195 | + s_ident * val = (s_ident *) bbTreeSeek (l->idIdx, seek); | |
| 196 | + | |
| 197 | +#ifdef DEBUG2 | |
| 198 | + printf ("[!DEBUG!] seek identNew: %d/%s\n", idx, ""); | |
| 199 | +#endif | |
| 200 | + | |
| 201 | + identFree (seek); | |
| 202 | + | |
| 203 | + return val; | |
| 204 | +} | |
| 205 | + | |
| 206 | + s_ident * | |
| 207 | +identListSeekKey (s_identList * l, const char * key) | |
| 208 | +{ | |
| 209 | + s_ident * seek = (s_ident *) identNew (-1, key); | |
| 210 | + s_ident * val = (s_ident *) bbTreeSeek (l->idHash, seek); | |
| 211 | + | |
| 212 | +#ifdef DEBUG2 | |
| 213 | + printf ("[!DEBUG!] seek identNew: %d/%s\n", -1, key); | |
| 214 | +#endif | |
| 215 | + | |
| 216 | + identFree (seek); | |
| 217 | + | |
| 218 | + return val; | |
| 219 | +} | |
| 220 | + | |
| 221 | +/* | |
| 222 | + * identList to other DataStructures | |
| 223 | + */ | |
| 224 | + s_ident ** | |
| 225 | +identListToArray (s_identList * l) | |
| 226 | +{ | |
| 227 | + int idIdxLen = bbTreeSize (l->idIdx); | |
| 228 | + int idHashLen = bbTreeSize (l->idHash); | |
| 229 | + int retLen = idIdxLen + idHashLen + 1; | |
| 230 | + s_ident ** ret = (s_ident **) malloc (sizeof (s_ident *) * retLen); | |
| 231 | + | |
| 232 | + memset (ret, 0, sizeof (s_ident **) * retLen); | |
| 233 | + | |
| 234 | + bbTreeInOrder (l->idIdx, (void **) ret); | |
| 235 | + bbTreeInOrder (l->idHash, (void **) &(ret[idIdxLen])); | |
| 236 | + | |
| 237 | + return ret; | |
| 238 | +} | ... | ... |
src/statement.c
0 → 100644
| 1 | +#include <malloc.h> | |
| 2 | +#include <stdio.h> | |
| 3 | + | |
| 4 | +#include <expValue.h> | |
| 5 | +#include <ident.h> | |
| 6 | +#include <evalExpr.h> | |
| 7 | +#include <evalCond.h> | |
| 8 | +#include <variable.h> | |
| 9 | +#include <assign.h> | |
| 10 | +#include <cast.h> | |
| 11 | +#include <tepal_pars.h> | |
| 12 | +#include <block.h> | |
| 13 | + | |
| 14 | +#include <statement.h> | |
| 15 | + | |
| 16 | +/* | |
| 17 | + * Deklaration und Definition | |
| 18 | + */ | |
| 19 | +#include <stmtQueue.h> | |
| 20 | + | |
| 21 | +struct stmt | |
| 22 | +{ | |
| 23 | + int sId; | |
| 24 | + s_stmtQueue * sQueue; | |
| 25 | + u_stmtType sConst; | |
| 26 | + int sConstTyp; | |
| 27 | +}; | |
| 28 | + | |
| 29 | +/* | |
| 30 | + * statische Funktionen (interner gebrauch) | |
| 31 | + */ | |
| 32 | +static | |
| 33 | +inline | |
| 34 | + u_stmtType | |
| 35 | +stmtEval (s_stmt * stmt, s_block * actBlock, int op) | |
| 36 | +{ | |
| 37 | + s_stmtQueue * args = stmt->sQueue; | |
| 38 | + s_expVal * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 39 | + * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal, | |
| 40 | + * ret; | |
| 41 | + | |
| 42 | + ret = evalExpr (op, op1, op2); | |
| 43 | + | |
| 44 | + if (op1 != NULL) expValueFree (op1); | |
| 45 | + if (op2 != NULL) expValueFree (op2); | |
| 46 | + | |
| 47 | + return (u_stmtType) ret; | |
| 48 | +} | |
| 49 | + | |
| 50 | +static | |
| 51 | +inline | |
| 52 | + u_stmtType | |
| 53 | +stmtIdentVar (s_stmt * stmt, s_block * actBlock) | |
| 54 | +{ | |
| 55 | + s_ident * ret = NULL; | |
| 56 | + | |
| 57 | + s_stmtQueue * args = stmt->sQueue; | |
| 58 | + s_expVal * _op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal; | |
| 59 | + char * op = expValueString (_op); | |
| 60 | + s_block * run = actBlock; | |
| 61 | + | |
| 62 | + while (ret == NULL && run != NULL) | |
| 63 | + { | |
| 64 | + ret = identListSeekKey (blockIdl (run), op); | |
| 65 | + run = blockPrev (run); | |
| 66 | + } | |
| 67 | + | |
| 68 | + if (ret == NULL) | |
| 69 | + ret = identListPutVal (blockIdl (actBlock), identUndefNew (-1, op)); | |
| 70 | + | |
| 71 | + expValueFree (_op); | |
| 72 | + free (op); | |
| 73 | + | |
| 74 | + return (u_stmtType) ret; | |
| 75 | +} | |
| 76 | + | |
| 77 | +static | |
| 78 | +inline | |
| 79 | + u_stmtType | |
| 80 | +stmtIdentArray (s_stmt * stmt, s_block * actBlock) | |
| 81 | +{ | |
| 82 | + s_stmtQueue * args = stmt->sQueue; | |
| 83 | + s_ident * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).idVal; | |
| 84 | + s_expVal * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal; | |
| 85 | + s_ident * ret; | |
| 86 | + | |
| 87 | + ret = getArray (op1, op2); | |
| 88 | + | |
| 89 | + if (op2 != NULL) expValueFree (op2); | |
| 90 | + | |
| 91 | + return (u_stmtType) ret; | |
| 92 | +} | |
| 93 | + | |
| 94 | +static | |
| 95 | +inline | |
| 96 | + u_stmtType | |
| 97 | +stmtIdentVal (s_stmt * stmt, s_block * actBlock) | |
| 98 | +{ | |
| 99 | + s_stmtQueue * args = stmt->sQueue; | |
| 100 | + s_ident * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).idVal; | |
| 101 | + | |
| 102 | + return (u_stmtType) identExp (op1); | |
| 103 | +} | |
| 104 | + | |
| 105 | +static | |
| 106 | +inline | |
| 107 | + u_stmtType | |
| 108 | +stmtEvalComp (s_stmt * stmt, s_block * actBlock, int op) | |
| 109 | +{ | |
| 110 | + s_stmtQueue * args = stmt->sQueue; | |
| 111 | + s_expVal * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 112 | + * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal; | |
| 113 | + int ret; | |
| 114 | + | |
| 115 | + ret = evalComp (op, op1, op2); | |
| 116 | + | |
| 117 | + if (op1 != NULL) expValueFree (op1); | |
| 118 | + if (op2 != NULL) expValueFree (op2); | |
| 119 | + | |
| 120 | + return (u_stmtType) ret; | |
| 121 | +} | |
| 122 | + | |
| 123 | +static | |
| 124 | +inline | |
| 125 | + u_stmtType | |
| 126 | +stmtAssign (s_stmt * stmt, s_block * actBlock) | |
| 127 | +{ | |
| 128 | + s_stmtQueue * args = stmt->sQueue; | |
| 129 | + s_ident * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).idVal; | |
| 130 | + s_expVal * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal, | |
| 131 | + * ret; | |
| 132 | + | |
| 133 | + if (op1 == NULL) | |
| 134 | + op1 = getVariable (NULL, NULL); | |
| 135 | + | |
| 136 | + ret = assign (op1, op2); | |
| 137 | + | |
| 138 | + if (op2 != NULL) expValueFree (op2); | |
| 139 | + | |
| 140 | + return (u_stmtType) ret; | |
| 141 | +} | |
| 142 | + | |
| 143 | +static | |
| 144 | +inline | |
| 145 | + u_stmtType | |
| 146 | +stmtPrint (s_stmt * stmt, s_block * actBlock) | |
| 147 | +{ | |
| 148 | + s_stmtQueue * args = stmt->sQueue; | |
| 149 | + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal; | |
| 150 | + | |
| 151 | + if (op != NULL) | |
| 152 | + { | |
| 153 | + printExpr (op); | |
| 154 | + expValueFree (op); | |
| 155 | + } | |
| 156 | + | |
| 157 | + return (u_stmtType) 0; | |
| 158 | +} | |
| 159 | + | |
| 160 | +static | |
| 161 | +inline | |
| 162 | + u_stmtType | |
| 163 | +stmtEvalCondExpr (s_stmt * stmt, s_block * actBlock) | |
| 164 | +{ | |
| 165 | + s_stmtQueue * args = stmt->sQueue; | |
| 166 | + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal; | |
| 167 | + int ret; | |
| 168 | + | |
| 169 | + ret = evalCondExpr (op); | |
| 170 | + | |
| 171 | + if (op != NULL) expValueFree (op); | |
| 172 | + | |
| 173 | + return (u_stmtType) ret; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static | |
| 177 | +inline | |
| 178 | + u_stmtType | |
| 179 | +stmtEvalCond (s_stmt * stmt, s_block * actBlock, int op) | |
| 180 | +{ | |
| 181 | + s_stmtQueue * args = stmt->sQueue; | |
| 182 | + int op1 = stmtDo (stmtQueueGet (args, 0), actBlock).cond; | |
| 183 | + | |
| 184 | + switch (op) | |
| 185 | + { | |
| 186 | + case LOGAND: | |
| 187 | + { | |
| 188 | + int op2 = stmtDo (stmtQueueGet (args, 1), actBlock).cond; | |
| 189 | + return (u_stmtType) (op1 && op2); | |
| 190 | + } | |
| 191 | + | |
| 192 | + case LOGOR: | |
| 193 | + { | |
| 194 | + int op2 = stmtDo (stmtQueueGet (args, 1), actBlock).cond; | |
| 195 | + return (u_stmtType) (op1 || op2); | |
| 196 | + } | |
| 197 | + | |
| 198 | + case LOGNEG: | |
| 199 | + return (u_stmtType) (! op1); | |
| 200 | + } | |
| 201 | +} | |
| 202 | + | |
| 203 | +static | |
| 204 | +inline | |
| 205 | + u_stmtType | |
| 206 | +stmtCastInt (s_stmt * stmt, s_block * actBlock) | |
| 207 | +{ | |
| 208 | + s_stmtQueue * args = stmt->sQueue; | |
| 209 | + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 210 | + * ret; | |
| 211 | + | |
| 212 | + ret = castExprToInt (op); | |
| 213 | + | |
| 214 | + if (op != NULL) expValueFree (op); | |
| 215 | + | |
| 216 | + return (u_stmtType) ret; | |
| 217 | +} | |
| 218 | + | |
| 219 | +static | |
| 220 | +inline | |
| 221 | + u_stmtType | |
| 222 | +stmtCastFloat (s_stmt * stmt, s_block * actBlock) | |
| 223 | +{ | |
| 224 | + s_stmtQueue * args = stmt->sQueue; | |
| 225 | + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 226 | + * ret; | |
| 227 | + | |
| 228 | + ret = castExprToFloat (op); | |
| 229 | + | |
| 230 | + if (op != NULL) expValueFree (op); | |
| 231 | + | |
| 232 | + return (u_stmtType) ret; | |
| 233 | +} | |
| 234 | + | |
| 235 | +static | |
| 236 | +inline | |
| 237 | + u_stmtType | |
| 238 | +stmtCastString (s_stmt * stmt, s_block * actBlock) | |
| 239 | +{ | |
| 240 | + s_stmtQueue * args = stmt->sQueue; | |
| 241 | + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 242 | + * ret; | |
| 243 | + | |
| 244 | + ret = castExprToString (op); | |
| 245 | + | |
| 246 | + if (op != NULL) expValueFree (op); | |
| 247 | + | |
| 248 | + return (u_stmtType) ret; | |
| 249 | +} | |
| 250 | + | |
| 251 | +static | |
| 252 | +inline | |
| 253 | + u_stmtType | |
| 254 | +stmtBlock (s_stmt * stmt, s_block * actBlock) | |
| 255 | +{ | |
| 256 | + unsigned int i; | |
| 257 | + | |
| 258 | + s_stmtQueue * gIds = stmtQueueGet (stmt->sQueue, 0)->sQueue; | |
| 259 | + s_stmtQueue * args = stmtQueueGet (stmt->sQueue, 1)->sQueue; | |
| 260 | + s_block * gBlock = NULL; | |
| 261 | + | |
| 262 | + gBlock = actBlock = blockPush (&actBlock, blockNew (args)); | |
| 263 | + | |
| 264 | + /* find the global block */ | |
| 265 | + while (blockPrev (gBlock) != NULL) | |
| 266 | + gBlock = blockPrev (gBlock); | |
| 267 | + | |
| 268 | + if (gIds != NULL) | |
| 269 | + { | |
| 270 | + for (i = 0; i < stmtQueueGetSize (gIds); i++) | |
| 271 | + { | |
| 272 | + s_expVal * tmp = stmtDo (stmtQueueGet (gIds, i), actBlock).eVal; | |
| 273 | + char * _id; | |
| 274 | + s_ident * id; | |
| 275 | + | |
| 276 | + if (tmp == NULL) | |
| 277 | + exitError (0); | |
| 278 | + | |
| 279 | + _id = expValueString (tmp); | |
| 280 | + id = identListSeekKey (blockGetIdl (gBlock), _id); | |
| 281 | + expValueFree (tmp); | |
| 282 | + free (_id); | |
| 283 | + | |
| 284 | + if (id == NULL) | |
| 285 | + exitError (0); | |
| 286 | + | |
| 287 | + blockSetNonLocalId (args, id); | |
| 288 | + } | |
| 289 | + } | |
| 290 | + | |
| 291 | + blockDo (actBlock); | |
| 292 | + blockFree (actBlock); | |
| 293 | + | |
| 294 | + return (u_stmtType) 0; | |
| 295 | +} | |
| 296 | + | |
| 297 | +static | |
| 298 | +inline | |
| 299 | + u_stmtType | |
| 300 | +stmtIf (s_stmt * stmt, s_block * actBlock) | |
| 301 | +{ | |
| 302 | + s_stmtQueue * args = stmt->sQueue; | |
| 303 | + int cond = stmtDo (stmtQueueGet (args, 0), actBlock).cond; | |
| 304 | + s_stmt * _do; | |
| 305 | + | |
| 306 | + if (cond) | |
| 307 | + _do = stmtQueueGet (args, 1); | |
| 308 | + else | |
| 309 | + _do = stmtQueueGet (args, 2); | |
| 310 | + | |
| 311 | + if (_do != NULL) | |
| 312 | + stmtDo (_do); | |
| 313 | + | |
| 314 | + return (u_stmtType) 0; | |
| 315 | +} | |
| 316 | + | |
| 317 | +static | |
| 318 | +inline | |
| 319 | + u_stmtType | |
| 320 | +stmtForeach (s_stmt * stmt, s_block * actBlock) | |
| 321 | +{ | |
| 322 | + s_stmtQueue * args = stmt->sQueue; | |
| 323 | + s_expVal * _id = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 324 | + * _key = stmtDo (stmtQueueGet (args, 1), actBlock).eVal, | |
| 325 | + * _val = stmtDo (stmtQueueGet (args, 2), actBlock).eVal; | |
| 326 | + char * id = expValueString (_id); | |
| 327 | + char * key = expValueString (_key); | |
| 328 | + char * val = expValueString (_val); | |
| 329 | + | |
| 330 | + printf ("[DEBUG]found foreach statement: id=%s, key=%s, val=%s\n", | |
| 331 | + id, key, val); | |
| 332 | + | |
| 333 | + free (id); | |
| 334 | + free (key); | |
| 335 | + free (val); | |
| 336 | + | |
| 337 | + expValueFree (_id); | |
| 338 | + expValueFree (_key); | |
| 339 | + expValueFree (_val); | |
| 340 | + | |
| 341 | + return (u_stmtType) 0; | |
| 342 | +} | |
| 343 | + | |
| 344 | +static | |
| 345 | +inline | |
| 346 | + u_stmtType | |
| 347 | +stmtRepeat (s_stmt * stmt, s_block * actBlock) | |
| 348 | +{ | |
| 349 | + s_stmtQueue * args = stmt->sQueue; | |
| 350 | + s_expVal * _id = stmtDo (stmtQueueGet (args, 0), actBlock).eVal, | |
| 351 | + * _count = stmtDo (stmtQueueGet (args, 1), actBlock).eVal; | |
| 352 | + char * id = expValueString (_id); | |
| 353 | + int count = expValueInt (_count); | |
| 354 | + | |
| 355 | + printf ("[DEBUG]found repeat statement: id=%s, count=%d\n", id, count); | |
| 356 | + | |
| 357 | + free (id); | |
| 358 | + | |
| 359 | + expValueFree (_id); | |
| 360 | + expValueFree (_count); | |
| 361 | + | |
| 362 | + return (u_stmtType) 0; | |
| 363 | +} | |
| 364 | + | |
| 365 | +/* | |
| 366 | + * Interface | |
| 367 | + */ | |
| 368 | + s_stmt * | |
| 369 | +stmtNew (int id, s_stmtQueue * queue, int conTyp, u_stmtType con) | |
| 370 | +{ | |
| 371 | + s_stmt * new = (s_stmt *) malloc (sizeof (s_stmt)); | |
| 372 | + | |
| 373 | + new->sId = id; | |
| 374 | + new->sQueue = queue; | |
| 375 | + new->sConstTyp = conTyp; | |
| 376 | + new->sConst = con; | |
| 377 | + | |
| 378 | + return new; | |
| 379 | +} | |
| 380 | + | |
| 381 | + s_stmtQueue * | |
| 382 | +stmtGetArgs (s_stmt * stmt) | |
| 383 | +{ | |
| 384 | + return stmt->sQueue; | |
| 385 | +} | |
| 386 | + | |
| 387 | + u_stmtType | |
| 388 | +stmtGetVal (s_stmt * stmt) | |
| 389 | +{ | |
| 390 | + return stmt->sConst; | |
| 391 | +} | |
| 392 | + | |
| 393 | + int | |
| 394 | +stmtGetConstTyp (s_stmt * stmt) | |
| 395 | +{ | |
| 396 | + return stmt->sConstTyp; | |
| 397 | +} | |
| 398 | + | |
| 399 | + void | |
| 400 | +stmtFree (s_stmt * stmt) | |
| 401 | +{ | |
| 402 | + if (stmt == NULL) | |
| 403 | + return; | |
| 404 | + | |
| 405 | + switch (stmt->sConstTyp) | |
| 406 | + { | |
| 407 | + case STYP_NONE: stmtQueueFree (stmt->sQueue); break; | |
| 408 | + case STYP_EVAL: expValueFree (stmt->sConst.eVal); break; | |
| 409 | + case STYP_IDVAL: identFree (stmt->sConst.idVal); break; | |
| 410 | + } | |
| 411 | + | |
| 412 | + free (stmt); | |
| 413 | +} | |
| 414 | + | |
| 415 | + u_stmtType | |
| 416 | +stmtDo (s_stmt * stmt, s_block * actBlock) | |
| 417 | +{ | |
| 418 | + if (stmt == NULL) | |
| 419 | + return (u_stmtType) 0; | |
| 420 | + | |
| 421 | + switch (stmt->sId) | |
| 422 | + { | |
| 423 | + case STMT_CONST: return (u_stmtType) expValueClone (stmt->sConst.eVal); | |
| 424 | + case STMT_BLOCK: return stmtBlock (stmt, actBlock); | |
| 425 | + | |
| 426 | + case STMT_PRINT: return stmtPrint (stmt, actBlock); | |
| 427 | + case STMT_IF: return stmtIf (stmt, actBlock); | |
| 428 | + case STMT_FOREACH: return stmtForeach (stmt, actBlock); | |
| 429 | + case STMT_REPEAT: return stmtRepeat (stmt, actBlock); | |
| 430 | + case STMT_ASSIGN: return stmtAssign (stmt, actBlock); | |
| 431 | + case STMT_UNSET: return (u_stmtType) 0; | |
| 432 | + | |
| 433 | + case STMT_EVAL_PLUS: return stmtEval (stmt, actBlock, PLUS); | |
| 434 | + case STMT_EVAL_MINUS: return stmtEval (stmt, actBlock, MINUS); | |
| 435 | + case STMT_EVAL_TIMES: return stmtEval (stmt, actBlock, TIMES); | |
| 436 | + case STMT_EVAL_OVER: return stmtEval (stmt, actBlock, OVER); | |
| 437 | + case STMT_EVAL_MODULO: return stmtEval (stmt, actBlock, MODULO); | |
| 438 | + case STMT_EVAL_NEG: return stmtEval (stmt, actBlock, NEG); | |
| 439 | + | |
| 440 | + case STMT_IDENT_VAR: return stmtIdentVar (stmt, actBlock); | |
| 441 | + case STMT_IDENT_ARRAY: return stmtIdentArray (stmt, actBlock); | |
| 442 | + case STMT_IDENT_VAL: return stmtIdentVal (stmt, actBlock); | |
| 443 | + | |
| 444 | + case STMT_CAST_INT: return stmtCastInt (stmt, actBlock); | |
| 445 | + case STMT_CAST_FLOAT: return stmtCastFloat (stmt, actBlock); | |
| 446 | + case STMT_CAST_STRING: return stmtCastString (stmt, actBlock); | |
| 447 | + | |
| 448 | + case STMT_COMP_EQ: return stmtEvalComp (stmt, actBlock, EQ); | |
| 449 | + case STMT_COMP_NE: return stmtEvalComp (stmt, actBlock, NE); | |
| 450 | + case STMT_COMP_LT: return stmtEvalComp (stmt, actBlock, LT); | |
| 451 | + case STMT_COMP_GT: return stmtEvalComp (stmt, actBlock, GT); | |
| 452 | + case STMT_COMP_LE: return stmtEvalComp (stmt, actBlock, LE); | |
| 453 | + case STMT_COMP_GE: return stmtEvalComp (stmt, actBlock, GE); | |
| 454 | + | |
| 455 | + case STMT_COND_EXPR: return stmtEvalCondExpr (stmt, actBlock); | |
| 456 | + case STMT_COND_AND: return stmtEvalCond (stmt, actBlock, LOGAND); | |
| 457 | + case STMT_COND_OR: return stmtEvalCond (stmt, actBlock, LOGOR); | |
| 458 | + case STMT_COND_NEG: return stmtEvalCond (stmt, actBlock, LOGNEG); | |
| 459 | + } | |
| 460 | +} | ... | ... |
src/stmtQueue.c
0 → 100644
| 1 | +#include <malloc.h> | |
| 2 | +#include <string.h> | |
| 3 | + | |
| 4 | +#include <ident.h> | |
| 5 | +#include <statement.h> | |
| 6 | +#include <block.h> | |
| 7 | + | |
| 8 | +#include <stmtQueue.h> | |
| 9 | + | |
| 10 | +/* give the queue an initial size for 10 statements */ | |
| 11 | +#define QUEUE_GROW_SIZE 10 | |
| 12 | + | |
| 13 | + | |
| 14 | +struct stmtQueue | |
| 15 | +{ | |
| 16 | + s_stmt ** stmts; /* a dynamically growing array of statements. */ | |
| 17 | + | |
| 18 | + unsigned int size; /* the actual size of the array in statements */ | |
| 19 | + unsigned int maxIdx; /* the maximum index used in the array. */ | |
| 20 | +}; | |
| 21 | + | |
| 22 | + s_stmtQueue * | |
| 23 | +stmtQueueNew (void) | |
| 24 | +{ | |
| 25 | + s_stmtQueue * new = (s_stmtQueue *) malloc (sizeof (s_stmtQueue)); | |
| 26 | + | |
| 27 | + new->size = QUEUE_GROW_SIZE; | |
| 28 | + new->maxIdx = 0; | |
| 29 | + new->stmts = (s_stmt **) calloc (sizeof (s_stmt *), new->size); | |
| 30 | + memset (new->stmts, 0, sizeof (s_stmt *) * new->size); | |
| 31 | + | |
| 32 | + return new; | |
| 33 | +} | |
| 34 | + | |
| 35 | +/* | |
| 36 | + * This concat does not change a or b, as opposed to the c strcat function | |
| 37 | + */ | |
| 38 | + s_stmtQueue * | |
| 39 | +stmtQueueConcat (s_stmtQueue * a, s_stmtQueue * b) | |
| 40 | +{ | |
| 41 | + s_stmtQueue * new = (s_stmtQueue *) malloc (sizeof (s_stmtQueue)); | |
| 42 | + | |
| 43 | + new->size = a->size + b->size; | |
| 44 | + new->maxIdx = a->maxIdx + b->maxIdx; | |
| 45 | + new->stmts = (s_stmt **) calloc (sizeof (s_stmt *), new->size); | |
| 46 | + memset (new->stmts, 0, sizeof (s_stmt *) * new->size); | |
| 47 | + | |
| 48 | + memcpy (new->stmts, a->stmts, sizeof (s_stmt *) * a->maxIdx); | |
| 49 | + memcpy (&(new->stmts[a->maxIdx]), b->stmts, sizeof (s_stmt *) * b->maxIdx); | |
| 50 | + | |
| 51 | + return new; | |
| 52 | +} | |
| 53 | + | |
| 54 | + void | |
| 55 | +stmtQueueFree (s_stmtQueue * sQueue) | |
| 56 | +{ | |
| 57 | + unsigned int i; | |
| 58 | + | |
| 59 | + if (sQueue == NULL) | |
| 60 | + return; | |
| 61 | + | |
| 62 | + /* freeing the queue is the final step. All stmts should be freed too! */ | |
| 63 | + for (i = 0; i < sQueue->maxIdx; i++) | |
| 64 | + stmtFree (sQueue->stmts [i]); | |
| 65 | + | |
| 66 | + free (sQueue->stmts); | |
| 67 | + free (sQueue); | |
| 68 | +} | |
| 69 | + | |
| 70 | + void | |
| 71 | +stmtQueueEnqueue (s_stmtQueue * sQueue, s_stmt * stmt) | |
| 72 | +{ | |
| 73 | + if (sQueue->maxIdx >= sQueue->size) | |
| 74 | + { | |
| 75 | + s_stmt ** stmtsOld = sQueue->stmts; | |
| 76 | + unsigned int newSize = sQueue->size + QUEUE_GROW_SIZE; | |
| 77 | + | |
| 78 | + sQueue->stmts = (s_stmt **) calloc (sizeof (s_stmt *), newSize); | |
| 79 | + memcpy (sQueue->stmts, stmtsOld, sizeof (s_stmt **) * sQueue->size); | |
| 80 | + free (stmtsOld); /* free the old queue but keep the statements */ | |
| 81 | + memset ( | |
| 82 | + &(sQueue->stmts[sQueue->size]), | |
| 83 | + 0, | |
| 84 | + sizeof (s_stmt **) * QUEUE_GROW_SIZE); | |
| 85 | + sQueue->size = newSize;; | |
| 86 | + } | |
| 87 | + | |
| 88 | + sQueue->stmts[sQueue->maxIdx ++] = stmt; | |
| 89 | +} | |
| 90 | + | |
| 91 | + s_stmt * | |
| 92 | +stmtQueueDequeue (s_stmtQueue * sQueue) | |
| 93 | +{ | |
| 94 | + s_stmt * ret = sQueue->stmts[sQueue->maxIdx - 1]; | |
| 95 | + | |
| 96 | + sQueue->stmts[-- sQueue->maxIdx] = NULL; | |
| 97 | + | |
| 98 | + return ret; | |
| 99 | +} | |
| 100 | + | |
| 101 | + s_stmt * | |
| 102 | +stmtQueueGet (s_stmtQueue * sQueue, unsigned int idx) | |
| 103 | +{ | |
| 104 | + if (idx < sQueue->size) | |
| 105 | + return sQueue->stmts [idx]; | |
| 106 | + else | |
| 107 | + return NULL; | |
| 108 | +} | |
| 109 | + | |
| 110 | + void | |
| 111 | +stmtQueueDo (s_stmtQueue * sQueue) | |
| 112 | +{ | |
| 113 | + int i; | |
| 114 | + | |
| 115 | + if (sQueue == NULL) | |
| 116 | + return; | |
| 117 | + | |
| 118 | + for (i = 0; i < sQueue->maxIdx; i++) | |
| 119 | + stmtDo (sQueue->stmts[i]); | |
| 120 | +} | |
| 121 | + | |
| 122 | + unsigned | |
| 123 | + int | |
| 124 | +stmtQueueGetSize (s_stmtQueue * sQueue) | |
| 125 | +{ | |
| 126 | + return sQueue->size; | |
| 127 | +} | ... | ... |
src/tepal.c
0 → 100644
| 1 | +#include <stdio.h> | |
| 2 | +#include <string.h> | |
| 3 | +#include <malloc.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | +#include <stdarg.h> | |
| 6 | + | |
| 7 | +#include <tepal_pars.h> | |
| 8 | +#include <expValue.h> | |
| 9 | +#include <ident.h> | |
| 10 | +#include <tepal.h> | |
| 11 | + | |
| 12 | +char * tepalErrMsg[] = | |
| 13 | +{ | |
| 14 | + "[ERROR] using uninitialized variable: %s\n", | |
| 15 | + "[ERROR] using array identifier without index: %s\n", | |
| 16 | + "[ERROR] unknown string operator: %c\n", | |
| 17 | + "[ERROR] unknown float operator: %c\n" | |
| 18 | +}; | |
| 19 | + | |
| 20 | + void | |
| 21 | +exitError (int errNum, ...) | |
| 22 | +{ | |
| 23 | + va_list ap; | |
| 24 | + | |
| 25 | + va_start (ap, errNum); | |
| 26 | + | |
| 27 | + switch (errNum) | |
| 28 | + { | |
| 29 | + case ERR_UNDEF_VAR: | |
| 30 | + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, char *)); | |
| 31 | + break; | |
| 32 | + | |
| 33 | + case ERR_NO_INDEX: | |
| 34 | + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, char *)); | |
| 35 | + break; | |
| 36 | + | |
| 37 | + case ERR_STRING_OPERATOR: | |
| 38 | + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, int)); | |
| 39 | + break; | |
| 40 | + | |
| 41 | + case ERR_FLOAT_OPERATOR: | |
| 42 | + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, int)); | |
| 43 | + break; | |
| 44 | + } | |
| 45 | + | |
| 46 | + va_end (ap); | |
| 47 | + exit (errNum); | |
| 48 | +} | |
| 49 | + | |
| 50 | +void | |
| 51 | +printExpr (s_expVal * val) | |
| 52 | +{ | |
| 53 | + switch (expValueGetType (val)) | |
| 54 | + { | |
| 55 | + case EXP_TYP_INT: printf ("%d", expValueInt (val)); break; | |
| 56 | + case EXP_TYP_FLOAT: printf ("%f", expValueFloat (val)); break; | |
| 57 | + case EXP_TYP_STRING: | |
| 58 | + { | |
| 59 | + char * v = expValueString (val); | |
| 60 | + printf (v); | |
| 61 | + free (v); | |
| 62 | + } | |
| 63 | + } | |
| 64 | +} | |
| 65 | + | ... | ... |
src/tepal_pars.y
0 → 100644
| 1 | +%{ | |
| 2 | +#include <malloc.h> | |
| 3 | +#include <string.h> | |
| 4 | +#include <stdio.h> | |
| 5 | +#include <stdlib.h> | |
| 6 | + | |
| 7 | +#include <tepal.h> | |
| 8 | +#include <evalCond.h> | |
| 9 | +#include <evalExpr.h> | |
| 10 | +#include <ident.h> | |
| 11 | +#include <identList.h> | |
| 12 | +#include <expValue.h> | |
| 13 | +#include <assign.h> | |
| 14 | +#include <variable.h> | |
| 15 | +#include <cast.h> | |
| 16 | +#include <stmtQueue.h> | |
| 17 | +#include <statement.h> | |
| 18 | + | |
| 19 | +extern int yylex (void); | |
| 20 | + | |
| 21 | + int | |
| 22 | +yywrap () | |
| 23 | +{ | |
| 24 | + return 1; | |
| 25 | +} | |
| 26 | + | |
| 27 | + void | |
| 28 | +yyerror (char const * s) | |
| 29 | +{ | |
| 30 | + fprintf(stderr, "%s\n", s); | |
| 31 | +} | |
| 32 | + | |
| 33 | +/* | |
| 34 | + * globale Variablen | |
| 35 | + */ | |
| 36 | +extern FILE * yyin; | |
| 37 | +extern s_block * _globalBlock_; | |
| 38 | + | |
| 39 | +s_stmtQueue * astRoot; | |
| 40 | + | |
| 41 | +/* | |
| 42 | + * statische Funktionen (zum lokalen gebrauch) | |
| 43 | + */ | |
| 44 | +static | |
| 45 | +inline | |
| 46 | + s_stmtQueue * | |
| 47 | +enqStmt (s_stmtQueue * sQueue, s_stmt * stmt) | |
| 48 | +{ | |
| 49 | + s_stmtQueue * ret = (sQueue == NULL) ? stmtQueueNew () : sQueue; | |
| 50 | + | |
| 51 | + stmtQueueEnqueue (ret, stmt); | |
| 52 | + return ret; | |
| 53 | +} | |
| 54 | + | |
| 55 | +static | |
| 56 | +inline | |
| 57 | + s_stmtQueue * | |
| 58 | +enqGlobId (s_stmtQueue * sQueue, char * id) | |
| 59 | +{ | |
| 60 | + s_stmtQueue * ret = (sQueue == NULL) ? stmtQueueNew () : sQueue; | |
| 61 | + s_stmt * val = stmtNew (STMT_CONST, NULL, STYP_EVAL, (u_stmtType) id); | |
| 62 | + | |
| 63 | + stmtQueueEnqueue (ret, id); | |
| 64 | + | |
| 65 | + return ret; | |
| 66 | +} | |
| 67 | + | |
| 68 | +static | |
| 69 | +inline | |
| 70 | + s_stmtQueue * | |
| 71 | +genBlockQue (s_stmtQueue * _gI, s_stmtQueue * _st) | |
| 72 | +{ | |
| 73 | + s_stmtQueue * ret = stmtQueueNew (); | |
| 74 | + s_stmt * gIds = stmtNew (STMT_BLOCK, _gI, STYP_NONE, (u_stmtType) 0); | |
| 75 | + s_stmt * stmts = stmtNew (STMT_BLOCK, _st, STYP_NONE, (u_stmtType) 0); | |
| 76 | + | |
| 77 | + stmtQueueEnqueue (ret, gIds); | |
| 78 | + stmtQueueEnqueue (ret, stmts); | |
| 79 | + | |
| 80 | + return ret; | |
| 81 | +} | |
| 82 | + | |
| 83 | +static | |
| 84 | +inline | |
| 85 | + s_stmt * | |
| 86 | +genIntStmt (long iVal) | |
| 87 | +{ | |
| 88 | + return stmtNew ( | |
| 89 | + STMT_CONST, | |
| 90 | + NULL, | |
| 91 | + STYP_EVAL, | |
| 92 | + (u_stmtType) expValueIntNew (iVal)); | |
| 93 | +} | |
| 94 | + | |
| 95 | +static | |
| 96 | +inline | |
| 97 | + s_stmt * | |
| 98 | +genFloatStmt (double fVal) | |
| 99 | +{ | |
| 100 | + return stmtNew ( | |
| 101 | + STMT_CONST, | |
| 102 | + NULL, | |
| 103 | + STYP_EVAL, | |
| 104 | + (u_stmtType) expValueFloatNew (fVal)); | |
| 105 | +} | |
| 106 | + | |
| 107 | +static | |
| 108 | +inline | |
| 109 | + s_stmt * | |
| 110 | +genStringStmt (s_stmt * stmt, char * string) | |
| 111 | +{ | |
| 112 | + s_stmt * ret = NULL; | |
| 113 | + s_expVal * eVal = NULL; | |
| 114 | + | |
| 115 | + char * new = NULL; | |
| 116 | + | |
| 117 | + if (stmt != NULL) | |
| 118 | + { | |
| 119 | + char * old = expValueString (stmtGetVal (stmt).eVal); | |
| 120 | + size_t len = strlen (old) + strlen (string) + 1; | |
| 121 | + | |
| 122 | + new = (char *) calloc (sizeof (char), len); | |
| 123 | + strcpy (new, old); | |
| 124 | + strcat (new, string); | |
| 125 | + | |
| 126 | + stmtFree (stmt); | |
| 127 | + free (old); | |
| 128 | + } | |
| 129 | + else | |
| 130 | + { | |
| 131 | + new = (char *)calloc (sizeof (char), strlen (string) + 1); | |
| 132 | + strcpy (new, string); | |
| 133 | + } | |
| 134 | + | |
| 135 | + eVal = expValueStringNew (new); | |
| 136 | + ret = stmtNew (STMT_CONST, NULL, STYP_EVAL, (u_stmtType) eVal); | |
| 137 | + free (new); | |
| 138 | + | |
| 139 | + free (string); | |
| 140 | + | |
| 141 | + return ret; | |
| 142 | +} | |
| 143 | + | |
| 144 | +static | |
| 145 | +inline | |
| 146 | + s_stmt * | |
| 147 | +genBlockStmt (s_stmtQueue * sQueue) | |
| 148 | +{ | |
| 149 | + return stmtNew (STMT_BLOCK, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 150 | +} | |
| 151 | + | |
| 152 | +static | |
| 153 | +inline | |
| 154 | + s_stmt * | |
| 155 | +genPrintStmt (s_stmt * stmt) | |
| 156 | +{ | |
| 157 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 158 | + | |
| 159 | + stmtQueueEnqueue (sQueue, stmt); | |
| 160 | + return stmtNew (STMT_PRINT, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 161 | +} | |
| 162 | + | |
| 163 | +static | |
| 164 | +inline | |
| 165 | + s_stmt * | |
| 166 | +genIfStmt (s_stmt * cond, s_stmt * _then, s_stmt * _else) | |
| 167 | +{ | |
| 168 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 169 | + | |
| 170 | + stmtQueueEnqueue (sQueue, cond); | |
| 171 | + stmtQueueEnqueue (sQueue, _then); | |
| 172 | + stmtQueueEnqueue (sQueue, _else); | |
| 173 | + | |
| 174 | + return stmtNew (STMT_IF, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 175 | +} | |
| 176 | + | |
| 177 | +static | |
| 178 | +inline | |
| 179 | + s_stmt * | |
| 180 | +genRepStmt (char * _ident, long _count, s_stmt * stmt) | |
| 181 | +{ | |
| 182 | + u_stmtType _id = (u_stmtType) expValueStringNew (_ident); | |
| 183 | + u_stmtType _co = (u_stmtType) expValueIntNew (_count); | |
| 184 | + s_stmt * ident = stmtNew (STMT_CONST, NULL, STYP_EVAL, _id); | |
| 185 | + s_stmt * count = stmtNew (STMT_CONST, NULL, STYP_EVAL, _co); | |
| 186 | + | |
| 187 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 188 | + | |
| 189 | + free (_ident); | |
| 190 | + | |
| 191 | + stmtQueueEnqueue (sQueue, ident); | |
| 192 | + stmtQueueEnqueue (sQueue, count); | |
| 193 | + stmtQueueEnqueue (sQueue, stmt); | |
| 194 | + | |
| 195 | + return stmtNew (STMT_REPEAT, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 196 | +} | |
| 197 | + | |
| 198 | +static | |
| 199 | +inline | |
| 200 | + s_stmt * | |
| 201 | +genForeStmt (char * _ident, char * _key, char * _val, s_stmt * stmt) | |
| 202 | +{ | |
| 203 | + u_stmtType _id = (u_stmtType) expValueStringNew (_ident); | |
| 204 | + u_stmtType _k = (u_stmtType) expValueStringNew (_key); | |
| 205 | + u_stmtType _v = (u_stmtType) expValueStringNew (_val); | |
| 206 | + s_stmt * ident = stmtNew (STMT_CONST, NULL, STYP_EVAL, _id); | |
| 207 | + s_stmt * key = stmtNew (STMT_CONST, NULL, STYP_EVAL, _k); | |
| 208 | + s_stmt * val = stmtNew (STMT_CONST, NULL, STYP_EVAL, _v); | |
| 209 | + | |
| 210 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 211 | + | |
| 212 | + free (_ident); | |
| 213 | + free (_key); | |
| 214 | + free (_val); | |
| 215 | + | |
| 216 | + stmtQueueEnqueue (sQueue, ident); | |
| 217 | + stmtQueueEnqueue (sQueue, key); | |
| 218 | + stmtQueueEnqueue (sQueue, val); | |
| 219 | + stmtQueueEnqueue (sQueue, stmt); | |
| 220 | + | |
| 221 | + return stmtNew (STMT_FOREACH, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 222 | +} | |
| 223 | + | |
| 224 | +static | |
| 225 | +inline | |
| 226 | + s_stmt * | |
| 227 | +genCondExprStmt (s_stmt * stmt) | |
| 228 | +{ | |
| 229 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 230 | + | |
| 231 | + stmtQueueEnqueue (sQueue, stmt); | |
| 232 | + return stmtNew (STMT_COND_EXPR, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 233 | +} | |
| 234 | + | |
| 235 | +static | |
| 236 | +inline | |
| 237 | + s_stmt * | |
| 238 | +genOpStmt (int op, s_stmt * op1, s_stmt * op2) | |
| 239 | +{ | |
| 240 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 241 | + int stmtId; | |
| 242 | + | |
| 243 | + stmtQueueEnqueue (sQueue, op1); | |
| 244 | + stmtQueueEnqueue (sQueue, op2); | |
| 245 | + | |
| 246 | + switch (op) | |
| 247 | + { | |
| 248 | + case LOGNEG: stmtId = STMT_COND_NEG; break; | |
| 249 | + case LOGAND: stmtId = STMT_COND_AND; break; | |
| 250 | + case LOGOR: stmtId = STMT_COND_OR; break; | |
| 251 | + case EQ: stmtId = STMT_COMP_EQ; break; | |
| 252 | + case NE: stmtId = STMT_COMP_NE; break; | |
| 253 | + case LT: stmtId = STMT_COMP_LT; break; | |
| 254 | + case GT: stmtId = STMT_COMP_GT; break; | |
| 255 | + case LE: stmtId = STMT_COMP_LE; break; | |
| 256 | + case GE: stmtId = STMT_COMP_GE; break; | |
| 257 | + case NEG: stmtId = STMT_EVAL_NEG; break; | |
| 258 | + case PLUS: stmtId = STMT_EVAL_PLUS; break; | |
| 259 | + case MINUS: stmtId = STMT_EVAL_MINUS; break; | |
| 260 | + case TIMES: stmtId = STMT_EVAL_TIMES; break; | |
| 261 | + case OVER: stmtId = STMT_EVAL_OVER; break; | |
| 262 | + case MODULO: stmtId = STMT_EVAL_MODULO; break; | |
| 263 | + } | |
| 264 | + | |
| 265 | + return stmtNew (stmtId, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 266 | +} | |
| 267 | + | |
| 268 | +static | |
| 269 | +inline | |
| 270 | + s_stmt * | |
| 271 | +genAssignStmt (s_stmt * var, s_stmt * val) | |
| 272 | +{ | |
| 273 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 274 | + | |
| 275 | + stmtQueueEnqueue (sQueue, var); | |
| 276 | + stmtQueueEnqueue (sQueue, val); | |
| 277 | + | |
| 278 | + return stmtNew (STMT_ASSIGN, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 279 | +} | |
| 280 | + | |
| 281 | +static | |
| 282 | +inline | |
| 283 | + s_stmt * | |
| 284 | +genIdMkGlobStmt (s_stmtQueue * sQueue) | |
| 285 | +{ | |
| 286 | + return stmtNew (/*another ID here*/STMT_BLOCK, | |
| 287 | + sQueue, STYP_NONE, (u_stmtType) 0); | |
| 288 | +} | |
| 289 | + | |
| 290 | +static | |
| 291 | +inline | |
| 292 | + s_stmt * | |
| 293 | +genIdentVarStmt (char * _ident) | |
| 294 | +{ | |
| 295 | + u_stmtType _id = (u_stmtType) expValueStringNew (_ident); | |
| 296 | + s_stmt * ident = stmtNew (STMT_CONST, NULL, STYP_EVAL, _id); | |
| 297 | + | |
| 298 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 299 | + | |
| 300 | + free (_ident); | |
| 301 | + | |
| 302 | + stmtQueueEnqueue (sQueue, ident); | |
| 303 | + return stmtNew (STMT_IDENT_VAR, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 304 | +} | |
| 305 | + | |
| 306 | +static | |
| 307 | +inline | |
| 308 | + s_stmt * | |
| 309 | +genIdentArrStmt (s_stmt * base, s_stmt * idx) | |
| 310 | +{ | |
| 311 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 312 | + | |
| 313 | + stmtQueueEnqueue (sQueue, base); | |
| 314 | + stmtQueueEnqueue (sQueue, idx); | |
| 315 | + | |
| 316 | + return stmtNew (STMT_IDENT_ARRAY, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 317 | +} | |
| 318 | + | |
| 319 | +static | |
| 320 | +inline | |
| 321 | + s_stmt * | |
| 322 | +genIdentValStmt (s_stmt * stmt) | |
| 323 | +{ | |
| 324 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 325 | + | |
| 326 | + stmtQueueEnqueue (sQueue, stmt); | |
| 327 | + return stmtNew (STMT_IDENT_VAL, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 328 | +} | |
| 329 | + | |
| 330 | +static | |
| 331 | +inline | |
| 332 | + s_stmt * | |
| 333 | +genCastIntStmt (s_stmt * stmt) | |
| 334 | +{ | |
| 335 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 336 | + | |
| 337 | + stmtQueueEnqueue (sQueue, stmt); | |
| 338 | + return stmtNew (STMT_CAST_INT, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 339 | +} | |
| 340 | + | |
| 341 | +static | |
| 342 | +inline | |
| 343 | + s_stmt * | |
| 344 | +genCastFloatStmt (s_stmt * stmt) | |
| 345 | +{ | |
| 346 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 347 | + | |
| 348 | + stmtQueueEnqueue (sQueue, stmt); | |
| 349 | + return stmtNew (STMT_CAST_FLOAT, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 350 | +} | |
| 351 | + | |
| 352 | +static | |
| 353 | +inline | |
| 354 | + s_stmt * | |
| 355 | +genCastStringStmt (s_stmt * stmt) | |
| 356 | +{ | |
| 357 | + s_stmtQueue * sQueue = stmtQueueNew (); | |
| 358 | + | |
| 359 | + stmtQueueEnqueue (sQueue, stmt); | |
| 360 | + return stmtNew (STMT_CAST_STRING, sQueue, STYP_NONE, (u_stmtType) 0); | |
| 361 | +} | |
| 362 | + | |
| 363 | +%} | |
| 364 | + | |
| 365 | +%token STMT_END ';' REPEAT COUNT FOREACH AS IF ELSE BLOCK_END UNSET | |
| 366 | +%token ICAST FCAST SCAST GLOBAL /* for explicit casts */ | |
| 367 | +%token <cPtr> IDENT | |
| 368 | +%token <cPtr> HTML | |
| 369 | +%token <iVal> INT | |
| 370 | +%token <fVal> FLOAT | |
| 371 | +%token <cPtr> STRING | |
| 372 | +%token <cPtr> EOL | |
| 373 | + | |
| 374 | +%left LOGAND LOGOR | |
| 375 | +%left LOGNEG | |
| 376 | +%nonassoc NE EQ LT GT LE GE | |
| 377 | + | |
| 378 | +%right '=' | |
| 379 | +%left '+' '-' | |
| 380 | +%left '*' '/' '%' | |
| 381 | +%left NEG | |
| 382 | +%nonassoc '(' ')' | |
| 383 | + | |
| 384 | +%union { | |
| 385 | + long iVal; | |
| 386 | + double fVal; | |
| 387 | + char * cPtr; | |
| 388 | + struct stmt * stmt; | |
| 389 | + struct stmtQueue * sQue; | |
| 390 | +} | |
| 391 | + | |
| 392 | +/* Es wird wohl darauf hinauslaufen das alles erstmal ein stmt wird | |
| 393 | + und in den AST wandert, und erst dann ausgewertet wird. Anders | |
| 394 | + wird es wohl nicht gehen. */ | |
| 395 | +%type <stmt> assig; | |
| 396 | +%type <stmt> ident; | |
| 397 | +%type <stmt> cond; | |
| 398 | +%type <stmt> comp; | |
| 399 | +%type <stmt> expr; | |
| 400 | +%type <stmt> html; | |
| 401 | +%type <stmt> block_stmt; | |
| 402 | +%type <stmt> gdecl_block; | |
| 403 | +%type <stmt> simple_stmt; | |
| 404 | +%type <stmt> if_stmt; | |
| 405 | +%type <stmt> rep_stmt; | |
| 406 | +%type <stmt> fore_stmt; | |
| 407 | +%type <stmt> stmt; | |
| 408 | +%type <sQue> stmt_queue; | |
| 409 | +%type <sQue> block_queue; | |
| 410 | +%type <sQue> glob_decl; | |
| 411 | + | |
| 412 | +%expect 1 | |
| 413 | + | |
| 414 | +%start script | |
| 415 | + | |
| 416 | +%% | |
| 417 | + | |
| 418 | +script : stmt_queue { astRoot = $1; } | |
| 419 | +; | |
| 420 | + | |
| 421 | +stmt_queue : stmt { $$ = enqStmt (NULL, $1); } | |
| 422 | + | stmt_queue stmt { $$ = enqStmt ($1, $2); } | |
| 423 | +; | |
| 424 | + | |
| 425 | +stmt : simple_stmt | |
| 426 | + | block_stmt | |
| 427 | + | if_stmt | |
| 428 | + | rep_stmt | |
| 429 | + | fore_stmt | |
| 430 | + | stmt_end stmt { $$ = $2; } | |
| 431 | +; | |
| 432 | + | |
| 433 | +simple_stmt : html stmt_end { $$ = genPrintStmt ($1); } | |
| 434 | + | expr stmt_end { $$ = genPrintStmt ($1); } | |
| 435 | + | assig stmt_end | |
| 436 | +; | |
| 437 | + | |
| 438 | +html : HTML { $$ = genStringStmt (NULL, $1); } | |
| 439 | + | html HTML { $$ = genStringStmt ($1, $2); } | |
| 440 | +; | |
| 441 | + | |
| 442 | +stmt_end : STMT_END | |
| 443 | + | ';' | |
| 444 | +; | |
| 445 | + | |
| 446 | +block_stmt : ':' BLOCK_END { $$ = genBlockStmt (NULL); } | |
| 447 | + | ':' block_queue BLOCK_END { $$ = genBlockStmt ($2); } | |
| 448 | +; | |
| 449 | + | |
| 450 | +block_queue : stmt_queue { $$ = genBlockQue (NULL, $1); } | |
| 451 | + | gdecl_block stmt_queue { $$ = genBlockQue ($1, $2); } | |
| 452 | +; | |
| 453 | + | |
| 454 | +/* | |
| 455 | + * Here follows the definitions for the "globals definition block" | |
| 456 | + * This is more complicated than first guessed, because these are no | |
| 457 | + * normal statements as all other constructs are. Escpecially in those | |
| 458 | + * block a newline should not be interpreted as statmend-end. | |
| 459 | + * ------ | |
| 460 | + */ | |
| 461 | +gdecl_block : GLOBAL ':' glob_decl BLOCK_END | |
| 462 | + { $$ = $3); } | |
| 463 | +; | |
| 464 | + | |
| 465 | +glob_decl : IDENT { $$ = enqGlobId (NULL, $1); } | |
| 466 | + | glob_decl ',' IDENT { $$ = enqGlobId ($1, $3); } | |
| 467 | +; | |
| 468 | +/* | |
| 469 | + * ------ | |
| 470 | + */ | |
| 471 | + | |
| 472 | +/* here is 1 shift/reduce conflict, but thats ok. */ | |
| 473 | +if_stmt : IF '(' cond ')' stmt { $$ = genIfStmt ($3, $5, NULL); } | |
| 474 | + | IF '(' cond ')' stmt ELSE stmt | |
| 475 | + { $$ = genIfStmt ($3, $5, $7); } | |
| 476 | +; | |
| 477 | + | |
| 478 | +rep_stmt : REPEAT '(' IDENT COUNT '=' INT ')' stmt | |
| 479 | + { $$ = genRepStmt ($3, $6, $8); } | |
| 480 | +; | |
| 481 | + | |
| 482 | +fore_stmt : FOREACH '(' IDENT AS IDENT ',' IDENT ')' stmt | |
| 483 | + { $$ = genForeStmt ($3, $5, $7, $9); } | |
| 484 | +; | |
| 485 | + | |
| 486 | +cond : expr { $$ = genCondExprStmt ($1); } | |
| 487 | + | comp { $$ = $1; } | |
| 488 | + | '(' comp ')' { $$ = $2; } | |
| 489 | + | '!' cond %prec LOGNEG { $$ = genOpStmt (LOGNEG, $2, NULL); } | |
| 490 | + | '(' '!' cond ')' %prec LOGNEG | |
| 491 | + { $$ = genOpStmt (LOGNEG, $3, NULL); } | |
| 492 | + | cond LOGAND cond { $$ = genOpStmt (LOGAND, $1, $3); } | |
| 493 | + | '(' cond LOGAND cond ')' { $$ = genOpStmt (LOGAND, $2, $4); } | |
| 494 | + | cond LOGOR cond { $$ = genOpStmt (LOGOR, $1, $3); } | |
| 495 | + | '(' cond LOGOR cond ')' { $$ = genOpStmt (LOGOR, $2, $4); } | |
| 496 | +; | |
| 497 | + | |
| 498 | +comp : expr EQ expr { $$ = genOpStmt (EQ, $1, $3); } | |
| 499 | + | expr NE expr { $$ = genOpStmt (NE, $1, $3); } | |
| 500 | + | expr LT expr { $$ = genOpStmt (LT, $1, $3); } | |
| 501 | + | expr GT expr { $$ = genOpStmt (GT, $1, $3); } | |
| 502 | + | expr LE expr { $$ = genOpStmt (LE, $1, $3); } | |
| 503 | + | expr GE expr { $$ = genOpStmt (GE, $1, $3); } | |
| 504 | +; | |
| 505 | + | |
| 506 | +assig : ident '=' expr { $$ = genAssignStmt ($1, $3); } | |
| 507 | + | ident '=' assig { $$ = genAssignStmt ($1, $3); } | |
| 508 | +; | |
| 509 | + | |
| 510 | +ident : IDENT { $$ = genIdentVarStmt ($1); } | |
| 511 | + | ident '[' expr ']' { $$ = genIdentArrStmt ($1, $3); } | |
| 512 | +; | |
| 513 | + | |
| 514 | +expr : ident { $$ = genIdentValStmt ($1); } | |
| 515 | + | INT { $$ = genIntStmt ($1); } | |
| 516 | + | FLOAT { $$ = genFloatStmt ($1); } | |
| 517 | + | STRING { $$ = genStringStmt (NULL, $1); } | |
| 518 | + | EOL { $$ = genStringStmt (NULL, $1); } | |
| 519 | + | |
| 520 | + | '(' ICAST ')' expr { $$ = genCastIntStmt ($4); } | |
| 521 | + | '(' FCAST ')' expr { $$ = genCastFloatStmt ($4); } | |
| 522 | + | '(' SCAST ')' expr { $$ = genCastStringStmt ($4); } | |
| 523 | + | '(' expr ')' { $$ = $2; } | |
| 524 | + | |
| 525 | + | '-' expr %prec NEG { $$ = genOpStmt (NEG, $2, NULL); } | |
| 526 | + | expr '+' expr { $$ = genOpStmt (PLUS, $1, $3); } | |
| 527 | + | expr '-' expr { $$ = genOpStmt (MINUS, $1, $3); } | |
| 528 | + | expr '*' expr { $$ = genOpStmt (TIMES, $1, $3); } | |
| 529 | + | expr '/' expr { $$ = genOpStmt (OVER, $1, $3); } | |
| 530 | + | expr '%' expr { $$ = genOpStmt (MODULO, $1, $3); } | |
| 531 | +; | |
| 532 | + | |
| 533 | +%% | |
| 534 | + | |
| 535 | +int | |
| 536 | +main (int argc, void * argv []) | |
| 537 | +{ | |
| 538 | + if (argc >= 2) | |
| 539 | + { | |
| 540 | + if ((yyin = fopen (argv[1], "r")) == NULL) | |
| 541 | + { | |
| 542 | + fprintf (stderr, "Could not open input file: %s\n", argv[1]); | |
| 543 | + fprintf (stderr, "Using stdin\n"); | |
| 544 | + yyin = stdin; | |
| 545 | + } | |
| 546 | + } | |
| 547 | + /* | |
| 548 | + * normally we would read from stdin if no file is given but for | |
| 549 | + * demonstration purpose we read a file from a standard location. | |
| 550 | + */ | |
| 551 | + else | |
| 552 | + { | |
| 553 | + if ((yyin = fopen ("/var/www/localhost/tpl/index.tpl", "r")) == NULL) | |
| 554 | + { | |
| 555 | + fprintf (stderr, "Could not open input file: %s\n", argv[1]); | |
| 556 | + fprintf (stderr, "Using stdin\n"); | |
| 557 | + yyin = stdin; | |
| 558 | + } | |
| 559 | + } | |
| 560 | + | |
| 561 | + printf ("Content-type: text/html\n\n"); | |
| 562 | + | |
| 563 | + astRoot = NULL; | |
| 564 | + yyparse (); | |
| 565 | + | |
| 566 | + _globalBlock_ = blockNew (astRoot); | |
| 567 | + | |
| 568 | + blockDo (_globalBlock_); | |
| 569 | + | |
| 570 | + if (_globalBlock_ != NULL); | |
| 571 | + blockFree (_globalBlock_); | |
| 572 | + | |
| 573 | + if (argc >= 2) | |
| 574 | + fclose (yyin); | |
| 575 | +} | ... | ... |
src/tepal_scan.l
0 → 100644
| 1 | +%{ | |
| 2 | +#include <malloc.h> | |
| 3 | +#include <string.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | + | |
| 6 | +#include <tepal_pars.h> | |
| 7 | +%} | |
| 8 | + | |
| 9 | +%x TOK | |
| 10 | + | |
| 11 | +DIGITS [0-9]+ | |
| 12 | +INT {DIGITS} | |
| 13 | +FLOAT {DIGITS}(.{DIGITS})? | |
| 14 | +STRING ('[^']*')|(\"[^\"]*\") | |
| 15 | +IDENT [a-zA-Z][_0-9a-zA-Z]*|_[0-9a-zA-Z]+ | |
| 16 | +OPERATOR [+\-*/%=,!:\[\]\(\);] | |
| 17 | + | |
| 18 | +ICAST int | |
| 19 | +FCAST float | |
| 20 | +SCAST string | |
| 21 | + | |
| 22 | +S_TOK [ \t]*<# | |
| 23 | +E_TOK #> | |
| 24 | +TEXT (\<[^#].*)|([^\<]*) | |
| 25 | + | |
| 26 | +%% | |
| 27 | + | |
| 28 | +{TEXT} { | |
| 29 | + char tok[2]; | |
| 30 | + size_t len = strlen (yytext); | |
| 31 | + | |
| 32 | + yylval.cPtr = (char *) malloc (len + 2); | |
| 33 | + memset (yylval.cPtr, 0, len + 2); | |
| 34 | + memcpy (yylval.cPtr, yytext, len); | |
| 35 | + | |
| 36 | + tok[0] = input (); | |
| 37 | + tok[1] = input (); | |
| 38 | + | |
| 39 | + if (tok[1] == '#' || tok[0] == EOF) | |
| 40 | + { | |
| 41 | + unput ('#'); | |
| 42 | + unput ('<'); | |
| 43 | + } | |
| 44 | + else | |
| 45 | + { | |
| 46 | + if (tok[1] != EOF) | |
| 47 | + unput (tok[1]); | |
| 48 | + yylval.cPtr[len] = tok[0]; | |
| 49 | + } | |
| 50 | + | |
| 51 | + #ifdef DEBUG | |
| 52 | + printf ("[TOKEN] HTML\n"); | |
| 53 | + #endif | |
| 54 | + | |
| 55 | + return HTML; | |
| 56 | + } | |
| 57 | + | |
| 58 | +{S_TOK} { | |
| 59 | + BEGIN (TOK); | |
| 60 | + #ifdef DEBUG | |
| 61 | + printf ("[TOKEN] STMT_END {[ \\t]*<#}\n"); | |
| 62 | + #endif | |
| 63 | + return STMT_END; | |
| 64 | + } | |
| 65 | + | |
| 66 | +<TOK>{E_TOK}\n? { | |
| 67 | + BEGIN (INITIAL); | |
| 68 | + | |
| 69 | + #ifdef DEBUG | |
| 70 | + printf ("[TOKEN] STMT_END {#>\\n?}\n"); | |
| 71 | + #endif | |
| 72 | + | |
| 73 | + return STMT_END; | |
| 74 | + } | |
| 75 | + | |
| 76 | +<TOK>{OPERATOR} { | |
| 77 | + #ifdef DEBUG | |
| 78 | + printf ("[TOKEN] %c\n", yytext[0]); | |
| 79 | + #endif | |
| 80 | + yylval.iVal = yytext[0]; | |
| 81 | + return yytext[0]; | |
| 82 | + } | |
| 83 | + | |
| 84 | +<TOK>== { | |
| 85 | + #ifdef DEBUG | |
| 86 | + printf ("[TOKEN] EQ\n"); | |
| 87 | + #endif | |
| 88 | + | |
| 89 | + return EQ; | |
| 90 | + } | |
| 91 | +<TOK>!= { | |
| 92 | + #ifdef DEBUG | |
| 93 | + printf ("[TOKEN] NE\n"); | |
| 94 | + #endif | |
| 95 | + | |
| 96 | + return NE; | |
| 97 | + } | |
| 98 | +<TOK>\< { | |
| 99 | + #ifdef DEBUG | |
| 100 | + printf ("[TOKEN] EQ\n"); | |
| 101 | + #endif | |
| 102 | + | |
| 103 | + return LT; | |
| 104 | + } | |
| 105 | +<TOK>\> { | |
| 106 | + #ifdef DEBUG | |
| 107 | + printf ("[TOKEN] EQ\n"); | |
| 108 | + #endif | |
| 109 | + | |
| 110 | + return GT; | |
| 111 | + } | |
| 112 | +<TOK>\<= { | |
| 113 | + #ifdef DEBUG | |
| 114 | + printf ("[TOKEN] EQ\n"); | |
| 115 | + #endif | |
| 116 | + | |
| 117 | + return LE; | |
| 118 | + } | |
| 119 | +<TOK>\>= { | |
| 120 | + #ifdef DEBUG | |
| 121 | + printf ("[TOKEN] EQ\n"); | |
| 122 | + #endif | |
| 123 | + | |
| 124 | + return GE; | |
| 125 | + } | |
| 126 | + | |
| 127 | +<TOK>&& { | |
| 128 | + #ifdef DEBUG | |
| 129 | + printf ("[TOKEN] LOGAND\n"); | |
| 130 | + #endif | |
| 131 | + | |
| 132 | + return LOGAND; | |
| 133 | + } | |
| 134 | +<TOK>\|\| { | |
| 135 | + #ifdef DEBUG | |
| 136 | + printf ("[TOKEN] LOGOR\n"); | |
| 137 | + #endif | |
| 138 | + | |
| 139 | + return LOGOR; | |
| 140 | + } | |
| 141 | + | |
| 142 | +<TOK>{INT} { | |
| 143 | + yylval.iVal = atol (yytext); | |
| 144 | + | |
| 145 | + #ifdef DEBUG | |
| 146 | + printf ("[TOKEN] INT\n"); | |
| 147 | + #endif | |
| 148 | + | |
| 149 | + return INT; | |
| 150 | + } | |
| 151 | + | |
| 152 | +<TOK>{FLOAT} { | |
| 153 | + yylval.fVal = atof (yytext); | |
| 154 | + | |
| 155 | + #ifdef DEBUG | |
| 156 | + printf ("[TOKEN] FLOAT\n"); | |
| 157 | + #endif | |
| 158 | + | |
| 159 | + return FLOAT; | |
| 160 | + } | |
| 161 | + | |
| 162 | +<TOK>{STRING} { | |
| 163 | + yylval.cPtr = (char *) malloc (strlen (yytext) - 1); | |
| 164 | + memset (yylval.cPtr, 0, strlen (yytext) - 1); | |
| 165 | + memcpy (yylval.cPtr, yytext + 1, strlen (yytext) - 2); | |
| 166 | + | |
| 167 | + #ifdef DEBUG | |
| 168 | + printf ("[TOKEN] STRING\n"); | |
| 169 | + #endif | |
| 170 | + | |
| 171 | + return STRING; | |
| 172 | + } | |
| 173 | + | |
| 174 | +<TOK>repeat { | |
| 175 | + #ifdef DEBUG | |
| 176 | + printf ("[TOKEN] REPEAT\n"); | |
| 177 | + #endif | |
| 178 | + | |
| 179 | + return REPEAT; | |
| 180 | + } | |
| 181 | +<TOK>count { | |
| 182 | + #ifdef DEBUG | |
| 183 | + printf ("[TOKEN] COUNT\n"); | |
| 184 | + #endif | |
| 185 | + | |
| 186 | + return COUNT; | |
| 187 | + } | |
| 188 | + | |
| 189 | +<TOK>foreach { | |
| 190 | + #ifdef DEBUG | |
| 191 | + printf ("[TOKEN] FOREACH\n"); | |
| 192 | + #endif | |
| 193 | + | |
| 194 | + return FOREACH; | |
| 195 | + } | |
| 196 | +<TOK>as { | |
| 197 | + #ifdef DEBUG | |
| 198 | + printf ("[TOKEN] AS\n"); | |
| 199 | + #endif | |
| 200 | + | |
| 201 | + return AS; | |
| 202 | + } | |
| 203 | + | |
| 204 | +<TOK>if { | |
| 205 | + #ifdef DEBUG | |
| 206 | + printf ("[TOKEN] IF\n"); | |
| 207 | + #endif | |
| 208 | + | |
| 209 | + return IF; | |
| 210 | + } | |
| 211 | +<TOK>else { | |
| 212 | + #ifdef DEBUG | |
| 213 | + printf ("[TOKEN] ELSE\n"); | |
| 214 | + #endif | |
| 215 | + | |
| 216 | + return ELSE; | |
| 217 | + } | |
| 218 | + | |
| 219 | +<TOK>end { | |
| 220 | + #ifdef DEBUG | |
| 221 | + printf ("[TOKEN] BLOCK_END\n"); | |
| 222 | + #endif | |
| 223 | + | |
| 224 | + return BLOCK_END; | |
| 225 | + } | |
| 226 | + | |
| 227 | +<TOK>unset { | |
| 228 | + #ifdef DEBUG | |
| 229 | + printf ("[TOKEN] UNSET\n"); | |
| 230 | + #endif | |
| 231 | + | |
| 232 | + return UNSET; | |
| 233 | + } | |
| 234 | + | |
| 235 | +<TOK>eol { | |
| 236 | + yylval.cPtr = (char *) calloc (sizeof (char), 2); | |
| 237 | + yylval.cPtr[0] = '\n'; | |
| 238 | + yylval.cPtr[1] = '\0'; | |
| 239 | + #ifdef DEBUG | |
| 240 | + printf ("[TOKEN] EOL\n"); | |
| 241 | + #endif | |
| 242 | + | |
| 243 | + return EOL; | |
| 244 | + } | |
| 245 | + | |
| 246 | +<TOK>parent { | |
| 247 | + #ifdef DEBUG | |
| 248 | + printf ("[TOKEN] PARENT\n"); | |
| 249 | + #endif | |
| 250 | + | |
| 251 | + return PARENT; | |
| 252 | + } | |
| 253 | + | |
| 254 | +<TOK>global { | |
| 255 | + #ifdef DEBUG | |
| 256 | + printf ("[TOKEN] GLOBAL\n"); | |
| 257 | + #endif | |
| 258 | + | |
| 259 | + return GLOBAL; | |
| 260 | + } | |
| 261 | + | |
| 262 | +<TOK>{ICAST} { | |
| 263 | + #ifdef DEBUG | |
| 264 | + printf ("[TOKEN] ICAST\n"); | |
| 265 | + #endif | |
| 266 | + | |
| 267 | + return ICAST; | |
| 268 | + } | |
| 269 | +<TOK>{FCAST} { | |
| 270 | + #ifdef DEBUG | |
| 271 | + printf ("[TOKEN] FCAST\n"); | |
| 272 | + #endif | |
| 273 | + | |
| 274 | + return FCAST; | |
| 275 | + } | |
| 276 | +<TOK>{SCAST} { | |
| 277 | + #ifdef DEBUG | |
| 278 | + printf ("[TOKEN] SCAST\n"); | |
| 279 | + #endif | |
| 280 | + | |
| 281 | + return SCAST; | |
| 282 | + } | |
| 283 | + | |
| 284 | +<TOK>{IDENT} { | |
| 285 | + yylval.cPtr = (char *) malloc (strlen (yytext) + 1); | |
| 286 | + strcpy (yylval.cPtr, yytext); | |
| 287 | + | |
| 288 | + #ifdef DEBUG | |
| 289 | + printf ("[TOKEN] IDENT\n"); | |
| 290 | + #endif | |
| 291 | + | |
| 292 | + return IDENT; | |
| 293 | + } | |
| 294 | + | |
| 295 | +<TOK>[ \t\r\n] { /* eat tokens */ } | ... | ... |
src/variable.c
0 → 100644
| 1 | +#include <stdio.h> | |
| 2 | +#include <malloc.h> | |
| 3 | + | |
| 4 | +#include <ident.h> | |
| 5 | +#include <expValue.h> | |
| 6 | +#include <variable.h> | |
| 7 | +#include <identList.h> | |
| 8 | + | |
| 9 | + | |
| 10 | + s_ident * | |
| 11 | +getVariable (identList * iList, char * id) | |
| 12 | +{ | |
| 13 | + return identListSeekKey (iList, id); | |
| 14 | +} | |
| 15 | + | |
| 16 | + s_ident * | |
| 17 | +getArray (s_ident * var, s_expVal * eVal) | |
| 18 | +{ | |
| 19 | + s_ident * ret = NULL; | |
| 20 | + | |
| 21 | + /* generate new idl if ident isn't, discard prev val */ | |
| 22 | + if (identGetType (var) != ID_TYP_IDL) | |
| 23 | + identSetIdl (var, identListNew (NULL)); | |
| 24 | + | |
| 25 | + /* now seek or generate the actual ident */ | |
| 26 | + switch (expValueGetType (eVal)) | |
| 27 | + { | |
| 28 | + case EXP_TYP_INT: | |
| 29 | + { | |
| 30 | + int idx = expValueInt (eVal); | |
| 31 | + | |
| 32 | + ret = identListSeekIdx (identIdl (var), idx); | |
| 33 | + | |
| 34 | + if (ret == NULL) | |
| 35 | + ret = identListPutVal ( | |
| 36 | + identIdl (var), identUndefNew (idx, NULL)); | |
| 37 | + | |
| 38 | + break; | |
| 39 | + } | |
| 40 | + | |
| 41 | + case EXP_TYP_STRING: | |
| 42 | + { | |
| 43 | + char * key = expValueString (eVal); | |
| 44 | + | |
| 45 | + ret = identListSeekKey (identIdl (var), key); | |
| 46 | + | |
| 47 | + if (ret == NULL) | |
| 48 | + ret = identListPutVal ( | |
| 49 | + identIdl (var), identUndefNew (-1, key)); | |
| 50 | + | |
| 51 | + free (key); | |
| 52 | + } | |
| 53 | + } | |
| 54 | + | |
| 55 | + return ret; | |
| 56 | +} | ... | ... |
Please
register
or
login
to post a comment