/media/sda-magnetic/david/Dokumente-15/fernuni-hagen/cs-i-ii/old-cs-2-01/comp-2021-09-07/compdos.c


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define F_MAX_LENGTH 8192
#define GLOBAL_VARS_N_MAX 8192+1
#define VAR_STR_MAX_LENGTH 128

#define E_TO_FEW_PROGRAM_ARGUMENTS -1
#define E_CANT_OPEN_FILE -2
#define E_SOURCE_FILE_EXCEEDED -3
#define E_SYNTAX_ERROR -4
#define E_NOT_ENOUGH_MEMORY -5

int global_vars [GLOBAL_VARS_N_MAX];

char lexstream [F_MAX_LENGTH];
char *lexstreamptr = lexstream;
int loopcount = 0;


int hash (char *);
int numexpr ();
int numexpr2 ();
int term ();
int term2 ();
int factor ();
char *arrayname ();
int boolexpr ();
int block ();
int block_do_not_execute ();
int loop () ;
int statement () ;
void stmt () ;
int ech () ;
int assignment ();
int cnd ();
 


int main (int argc, char *argv []) {
    FILE *fp;
    int ch;
    
    char *p;
    int i;

    char lexstreamtmp [F_MAX_LENGTH];
    char *p1, *p2;
    
    if (argc != 2) {
        perror ("Too few arguments for program");
        return E_TO_FEW_PROGRAM_ARGUMENTS;
    }
    if ((fp = fopen (argv [1], "r")) == NULL) {
        perror ("Can't open file");
        return E_CANT_OPEN_FILE;
    }
    
    i = 0;
    p = lexstream;
    while (!feof(fp)) {
        ch = fgetc (fp);
        if (i > 8129) {
            perror ("Source File to long");
            return E_SOURCE_FILE_EXCEEDED;
        }
        i++;
        *p = ch;
        p++;
    }
    *p = 0;
    
    lexstreamptr = lexstream;
    
    
    for (p1 = lexstream, p2 = lexstreamtmp;  (*p1) != 0;  p1++, p2++) {
        if ((*p1) == '\n')
            (*p2) = ' ';
        else if ((*p1) == '\t')
            (*p2) = ' ';
        else if ((*p1) == '\r')
            (*p2) = ' ';
        else
            (*p2) = (*p1);
    }
    (*p2) = 0;

    
    for (p1 = lexstream, p2 = lexstreamtmp;  (*p2) != 0;  p2++) {
        (*p1) = (*p2);
        if (!(((*p2) == ' ') && ((*(p2+1)) == ' ')))
            p1++;
    }
    (*p1) = 0;
    
    statement ();
    
return 0;    
}


int hash (char *v) {
    int h;
    
    for (h = 0;  *v != 0;  v++)
        h = (128*h+*v) % GLOBAL_VARS_N_MAX;
return h;
}

int numexpr () {
    int x;
    int y;
    
    x = term ();
    y = numexpr2 ();
    return x+y;
}

int numexpr2 () {
    char *ptrtmp;
    int x, y;
    
    ptrtmp = lexstreamptr;
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;
    if ((*lexstreamptr) == '+') {
        lexstreamptr++;
        x = term ();
        y = numexpr2 ();
        return x+y;
    }
    if ((*lexstreamptr) == '-') {
        lexstreamptr++;
        x = term ();
        y = numexpr2 ();
        return -x+y;
    }
    lexstreamptr = ptrtmp;
    return 0;
}

int term () {
    int x, y;
    
    x = factor ();
    y = term2 ();
    return x*y;
}

int term2 () {
    int x, y;
    char *ptrtmp;
    
    ptrtmp = lexstreamptr;
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;
    if ((*lexstreamptr) == '*') {
        lexstreamptr++;
        x = factor ();
        y = term2 ();
        return x*y;
    }
    if ((*lexstreamptr) == '/') {
        lexstreamptr++;
        x = factor ();
        y = term2 ();
        return y/x;
    }
    lexstreamptr = ptrtmp;
    return 1;
}

int factor () {
    int intret;
    char intstrtmp [VAR_STR_MAX_LENGTH];
    int retval;
    char *ptr;
    char varname [VAR_STR_MAX_LENGTH];
    char *arraynamestr;
    char buf [128];
    
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;

    intret = atoi (lexstreamptr, NULL);
    
    if (((*lexstreamptr) != '0') && (intret != 0)) {
        sprintf (intstrtmp, "%i", intret);
        lexstreamptr += strlen (intstrtmp);
        return intret;
    }
    else if ((*lexstreamptr) == '0') {
        sprintf (intstrtmp, "%i", intret);
        lexstreamptr += strlen (intstrtmp);
        return intret;
    }
    else if ((*lexstreamptr) == '(') {
        lexstreamptr ++;
        retval = numexpr ();
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        if ((*lexstreamptr) != ')') { 
            perror ("Forget round bracket in arithmetic expression");
            return E_SYNTAX_ERROR;
        }
        lexstreamptr ++;
        return retval;
    }
    else if ((*lexstreamptr) == '$') {
        lexstreamptr++;
        
        if (!((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z'))) {
            perror ("bad variable name");
            return E_SYNTAX_ERROR;
        }
        ptr = varname;
        while ((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z')) {
            *ptr = *lexstreamptr;
            ptr++;
            lexstreamptr++;
        }
        *ptr = 0;
        arraynamestr = arrayname ();
        if (arraynamestr != NULL)
            strcat (varname, arraynamestr);
        return global_vars [hash (varname)];
    }
    else {
        perror ("error in arithmetic expression");
        return E_SYNTAX_ERROR;
    }
}

char *arrayname () {
    char *lexstreamptrtmp = lexstreamptr;
    char *lexstreamptrtmp2;
    char *arrayindexstr;
    char *arraynamestrpost;
    
    if ((arrayindexstr = (char *) malloc (VAR_STR_MAX_LENGTH)) == NULL) {
        perror ("Not enough memory");
        exit( E_NOT_ENOUGH_MEMORY );
    }
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;

    if ((*lexstreamptr) == '[') {
        lexstreamptr++;
        sprintf (arrayindexstr, "%i", (int) numexpr());
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        if ((*lexstreamptr) != ']') {
            perror ("Forgot closing array bracket");
            exit ( E_SYNTAX_ERROR );
        }
        lexstreamptr++;
        
        lexstreamptrtmp2 = lexstreamptr;
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        if ((*lexstreamptr) == '[') {
            lexstreamptr = lexstreamptrtmp2;
            arraynamestrpost = arrayname ();
            if (arraynamestrpost != NULL)
                strcat (arrayindexstr, arraynamestrpost);
        }
        else
            lexstreamptr = lexstreamptrtmp2;
        return arrayindexstr;    
    }
    else {
        free (arrayindexstr);
        lexstreamptr = lexstreamptrtmp;
        return NULL;
    }
}

int boolexpr () {
    int x, y;
    
    x = numexpr ();
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;

    if ((*lexstreamptr) == '<') {
        lexstreamptr++;
        y = numexpr ();
        return (x < y);
    }
    else if ((*lexstreamptr) == '>') {
        lexstreamptr++;
        y = numexpr ();
        return (x > y);
    }
    else if (((*lexstreamptr) == '<') && (*(lexstreamptr+1) == '=')) {
        lexstreamptr+=2;
        y = numexpr ();
        return (x <= y);
    }
    else if (((*lexstreamptr) == '>') && (*(lexstreamptr+1) == '=')) {
        lexstreamptr+=2;
        y = numexpr ();
        return (x >= y);
    }
    else if (((*lexstreamptr) == '=') && (*(lexstreamptr+1) == '=')) {
        lexstreamptr+=2;
        y = numexpr ();
        return (x == y);
    }
    else if (((*lexstreamptr) == '!') && (*(lexstreamptr+1) == '=')) {
        lexstreamptr+=2;
        y = numexpr ();
        return (x != y);
    }
    else {
        perror ("Wrong compare operator in boolesche expression");
        exit ( E_SYNTAX_ERROR );
    }
}

int block () {
    char *lexstreamptrtmp = lexstreamptr;
    
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;
    if (strncmp (lexstreamptr, "begin", strlen ("begin")) == 0) {
        lexstreamptr += strlen ("begin");
        statement ();
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        if (strncmp (lexstreamptr, "end", strlen ("end")) == 0)
            lexstreamptr += strlen ("end");
        else {
            perror ("forgot end in block");
            exit ( E_SYNTAX_ERROR );
        }
    }
    else {
        perror ("forgot begin in block");
        exit ( E_SYNTAX_ERROR );
    }
}

int block_do_not_execute () {
    int count = 1;
    
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;

    if (strncmp (lexstreamptr, "begin", strlen ("begin")) == 0) {
        lexstreamptr += strlen ("begin");
        while ((*lexstreamptr) != 0) {
            if ((*lexstreamptr) == ' ')
                lexstreamptr++;
            if (strncmp (lexstreamptr, "end", strlen ("end")) == 0) {
                lexstreamptr += strlen ("end");
                count--;
            }
            else if (count == 0)
                break;
            else if (strncmp (lexstreamptr, "begin", strlen ("begin")) == 0) {
                lexstreamptr += strlen ("begin");
                count++;
            }
            else 
                lexstreamptr ++;
        }
        if (count != 0) {
            perror ("code ends before block cloesd");
            exit ( E_SYNTAX_ERROR );
        }
    }
    else {
        perror ("forgot begin in block");
        exit ( E_SYNTAX_ERROR );
    }

}

int loop () {
    char *lexstreamptrtmp = lexstreamptr;
    
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;

    if (strncmp (lexstreamptr, "while", strlen ("while")) == 0) {
        lexstreamptr += strlen ("while");
        if (boolexpr ()) {
            if ((*lexstreamptr) == ' ')
                lexstreamptr++;

            if (strncmp (lexstreamptr, "do", strlen ("do")) == 0) {
                lexstreamptr += strlen ("do");
                block ();
                lexstreamptr = lexstreamptrtmp;
                loop ();
                return 1;
            }
            else  {
                perror ("Forgot do in while statement");
                exit ( E_SYNTAX_ERROR );
            }
        }
        else {
            if ((*lexstreamptr) == ' ')
                lexstreamptr++;
            if (strncmp (lexstreamptr, "do", strlen ("do")) == 0) {
                lexstreamptr += strlen ("do");
                block_do_not_execute ();
                return 1;
            }
            else {
                perror ("Forgot do in while statement");
                exit ( E_SYNTAX_ERROR );
            }
        }
    }
    else {
        lexstreamptr = lexstreamptrtmp;
        return 0;
    }
    
}

int statement () {
    char *lexstreamptrtmp = lexstreamptr;
    char *lexstreamptrtmp2;
    stmt ();
    lexstreamptrtmp2 = lexstreamptr;
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;
    if ((*lexstreamptr) == ';') {
        lexstreamptr++;
        statement ();
    }
    else 
        lexstreamptr = lexstreamptrtmp2;
}

void stmt () {
    if (loop ());
    else if (assignment ());
    else if (cnd ());
    else if (ech ());
}

int ech () {
    char *lexstreamptrtmp = lexstreamptr;
        
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;
    if (strncmp (lexstreamptr, "echo", strlen ("echo")) == 0) {
        lexstreamptr += strlen ("echo");
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        printf ("%i\n", numexpr ());
        return 1;
    }
    else {
        lexstreamptr = lexstreamptrtmp; 
        return 0;
    }
}

int assignment () {
    char *lexstreamptrtmp = lexstreamptr;
    char *arraynamestr;
    char varname [VAR_STR_MAX_LENGTH];
    char *ptr;  
        
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;
    
    if ((*lexstreamptr) == '$') {
        lexstreamptr++;
        
        if (!((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z'))) {
            perror ("bad variable name");
            exit ( E_SYNTAX_ERROR );
        }
        
        ptr = varname;
    
        while ((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z')) {
            *ptr = *lexstreamptr;
            ptr++;
            lexstreamptr++;
        }
        *ptr = 0;
    
        arraynamestr = arrayname ();
        if (arraynamestr != NULL)
            strcat (varname, arraynamestr);
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        if ((*(lexstreamptr) == ':') && (*(lexstreamptr+1) == '=')) {
            lexstreamptr += 2;
            global_vars [hash (varname)] = numexpr ();
            return 1;
        }
        else {
            lexstreamptr = lexstreamptrtmp;
            return 0;
        }
    }
    else {
        lexstreamptr = lexstreamptrtmp;
        return 0;
    }
}

int cnd () {
    char *lexstreamptrtmp = lexstreamptr;
    char *lexstreamptrtmp2;
    int flag;
    
    if ((*lexstreamptr) == ' ')
        lexstreamptr++;

    if (strncmp (lexstreamptr, "if", strlen ("if")) == 0) {
        lexstreamptr += strlen ("if");
        
        flag = boolexpr ();
        if ((*lexstreamptr) == ' ')
            lexstreamptr++;
        if (strncmp (lexstreamptr, "then", strlen ("then")) == 0) {
            lexstreamptr += strlen ("then");
            if (flag) {
                block ();
                lexstreamptrtmp2 = lexstreamptr;
                if ((*lexstreamptr) == ' ')
                    lexstreamptr++;
                if (strncmp (lexstreamptr, "else", strlen ("else")) == 0) {
                    lexstreamptr += strlen ("else");
                    block_do_not_execute ();
                }
                else
                    lexstreamptr = lexstreamptrtmp2;
                return 1;
            }
            else {
                block_do_not_execute ();
                lexstreamptrtmp = lexstreamptr;
                if ((*lexstreamptr) == ' ')
                    lexstreamptr++;
                if (strncmp (lexstreamptr, "else", strlen ("else")) == 0) {
                    lexstreamptr += strlen ("else");
                    block ();
                }
                else
                    lexstreamptr = lexstreamptrtmp2;
                return 1;
            }
        }
        else {
            perror ("Forget then in if-Statement");
            exit (E_SYNTAX_ERROR);
        }
    }
    else {
        lexstreamptr = lexstreamptrtmp;
        return 0;
    }
        
}