/media/sda-magnetic/david/Dok-15-2023-11-27/informatik/AUTOMAT-GENERATOR-2024-01-28/asmparser10.c


/*
Grammatik

Sporadische Sammlung
- Zuweisung
- Addition
if 
- Vergleiche
    - <=, >=, ==, !=, <, >
- Subtraktion
- Shift
    << >>
- Null setzen
    
Operationen
    - Mathematische: 
        + (Addition)
        - (Subtraktion) 
    - Verschieben
        >> Rechtsshift
        << Linksshift
    - 0 setzen 
Vergleiche
    - <=, >=, ==, !=, <, >
Zuweisung
    <-
    
Zeichensatz: Variablen, Register, Operatoren und Konstante Werte

Operand ::= <Register> | <Const>
CMP ::= <= | >= | == | != | < | >
MathOperator ::= + | - | << | >>
BitBooleanOperator ::= '&&' | '||' | '!'
Operator ::= <MathOperator> | <BitBooleanOperator>
Expr ::= <Register> <- <Operand> | <Operand> <Operator> <Operand> | 0
Condition ::= IF <Register> <CMP> <Operand> THEN <Program> FI

Programm ::= <Expr> | <Condition> <Program>
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define     MAX_STATES                              1024
#define     MAX_EXPR_CONST_VAL                      128
#define     MAX_EXPR_REG_VAL                        4
#define     FIRST_REG_VAL                           'a'
#define     MAX_EXPR_OPERATOR_VAL                   6
#define     MAX_EXPR_CMP_OPERATOR_VAL               5
#define     RAND_OPERAND_CONST_REGISTER             2
#define     RAND_EXPR_OPERATOR_OPERAND_FOLLOW       2
#define     RAND_COND_TRUE_FALSE_DESICION           2
#define     RAND_PROGRAM_COND_EXPR_DESICION         4
#define     IF_ELSE_DEPTH                           3
#define     STD_PROGRAM_N                           6   
#define     STD_PROGRAM2_N                          4
#define     RAND_COND_END_OR_GO_ON                  3

FILE *fout = NULL;

int line = 0;
int nline = 1;
int maxstate = 0;

char *opstr [] = {"+", "-", "<<", ">>", "&&", "||", "!"};
char *cmpstr [] = {"<=", ">=", "==", "!=", "<", ">"};


void registr (void) {
    printf (" %c ", (rand () % MAX_EXPR_REG_VAL) + FIRST_REG_VAL);
return;
}

void cnst (void) {
    printf (" %i ", rand () % MAX_EXPR_CONST_VAL);
return;
}

void operator (void) {
    printf (" %s ", opstr [rand () % MAX_EXPR_OPERATOR_VAL]);
return;
}

void cmp (void) {
    printf (" %s ", cmpstr [rand () % MAX_EXPR_CMP_OPERATOR_VAL]);
return;
}

void operand (void) {
    if ((rand () % RAND_OPERAND_CONST_REGISTER) == 0)
        cnst ();
    else
        registr ();
return;
}

#define NO      0
#define WEST    1
#define EAST    2

#define MAX_NODES                   64
#define STACKS_MAX                  4

char *op_names [] = {"==", \
    "!=", \
    ">", \
    ">=", \
    "<", \
    "<=", \
    "+", \
    "++", \
    "-", \
    "--", \
    "<<", \
    ">>", \
    "<|", \
    "|>", \
    "and", \
    "not", \
    "or", \
    "xor", \
    "+", \
    "++", \
    "-", \
    "--", \
    "<<", \
    ">>", \
    "<|", \
    "|>", \
    "and", \
    "not", \
    "or", \
    "xor", \
    "<-"
};

#define OP_CMP_EQ_REG_CONST         0
#define OP_CMP_NE_REG_CONST         1
#define OP_CMP_GR_REG_CONST         2
#define OP_CMP_GE_REG_CONST         3
#define OP_CMP_LT_REG_CONST         4
#define OP_CMP_LE_REG_CONST         5
#define OP_ADD_REG_REG_CONST        6
#define OP_INC_REG_REG_CONST        7
#define OP_SUB_REG_REG_CONST        8
#define OP_DEC_REG_REG_CONST        9
#define OP_SLL_REG_REG_CONST        10
#define OP_SLR_REG_REG_CONST        11
#define OP_RL_REG_REG_CONST       12
#define OP_RR_REG_REG_CONST       13
#define OP_AND_REG_REG_CONST      14
#define OP_NOT_REG_REG_CONST      15
#define OP_OR_REG_REG_CONST       16
#define OP_EXOR_REG_REG_CONST     17
#define OP_ADD_REG_REG_REG        18
#define OP_INC_REG_REG_REG        19
#define OP_SUB_REG_REG_REG        20
#define OP_DEC_REG_REG_REG        21
#define OP_SLL_REG_REG_REG        22
#define OP_SLR_REG_REG_REG        23
#define OP_RL_REG_REG_REG         24
#define OP_RR_REG_REG_REG         25
#define OP_AND_REG_REG_REG        26
#define OP_NOT_REG_REG_REG        27
#define OP_OR_REG_REG_REG         28
#define OP_EXOR_REG_REG_REG       29
#define OP_ASSIGNMENT_REG_CONST   30
#define NA                        -1
#define EMPTY                       -2

#define STACK_OPCODE                0
#define STACK_OP1                   1
#define STACK_OP2                   2
#define STACK_OP3                   3

#define MAX_COND                    3
#define CONST_MAX                   32


int stack [STACKS_MAX][MAX_NODES];
int stack2 [MAX_NODES];
int stack_ptr [STACKS_MAX];
int queue_ptr [STACKS_MAX];
int stack_ptr2 = 0;

void init_stack (void) {
    int i;
    for (i = 0;  i < STACKS_MAX;  i++) {
        stack_ptr [i] = 0;
    }
return;
}

void queue_init (void) {
    int i;
    for (i = 0;  i < STACKS_MAX;  i++) {
        queue_ptr [i] = 0;
    }
return;
}

void push (int stck, int v) {
    if (stack_ptr[stck] < (MAX_NODES-1)) {
        stack [stck][stack_ptr [stck]] = v;
        stack_ptr [stck]++;
    }
return;
}

int pop (int stck) {
    if (stack_ptr [stck] > 0) {
        stack_ptr [stck]--;
        return stack [stck][stack_ptr [stck]];
    }
}

int get (int stck) {
    if (queue_ptr [stck] < stack_ptr [stck]) {
        return stack [stck][queue_ptr [stck]++];
    }
    else return EMPTY;
}


void push2 (int v) {
    if (stack_ptr2 < (MAX_NODES-1)) {
        stack2 [stack_ptr2] = v;
        stack_ptr2++;
    }
}

int pop2 (void) {
    if (stack_ptr2 > 0) {
        stack_ptr2--;
        return stack2 [stack_ptr2];
    }
}

int regmax = 0;


/*
 * reg ::= op reg reg reg | op reg reg const | op const
 * cond ::= op_cmp reg const addr1 addr2
 */

void init () {
    int i = 0;
    int cond_count = MAX_COND;
    int cond_least = 0;
    int op;
    int imax = (rand () % 6) + 5;
    int lastreg;

    push (STACK_OPCODE, OP_ASSIGNMENT_REG_CONST);           // Assignment at begin
    push (STACK_OP1, 0);                                    // Register R0 ()
    push (STACK_OP2, rand () % CONST_MAX);                  // Const
    push (STACK_OP3, NA);                                   // Operand 3, assignment, not given

    for (i = 1;  i < imax;  i++) {
        op = rand () % (OP_EXOR_REG_REG_REG+1);
        if ((op < OP_CMP_LE_REG_CONST) && (cond_least == 0)) {
            if (cond_count > 0) {
                cond_count--;
                lastreg = pop (STACK_OP1);
                push (STACK_OP1, lastreg);
                push (STACK_OPCODE, op);
                push (STACK_OP1, lastreg);
                push (STACK_OP2, rand () % CONST_MAX);
                push (STACK_OP3, NA );
                cond_least = 2;
                if ((i + cond_least) > imax)
                    imax += cond_least;
                push2 (i);
            }
            else {
                i--;
            }
        }
        else {
                if (cond_least != 0)
                    cond_least--;
                lastreg = pop (STACK_OP1);
                push (STACK_OP1, lastreg);
                push (STACK_OPCODE, op);
                push (STACK_OP1, lastreg+1);
                push (STACK_OP2, lastreg);
                if ((op >= OP_ADD_REG_REG_REG) && (op <= OP_EXOR_REG_REG_REG))
                    push (STACK_OP3, (rand () % (lastreg+1))-1);
                else
                    push (STACK_OP3, rand () % CONST_MAX);
        }
    }
    push (STACK_OPCODE, EMPTY);
    push (STACK_OP1, EMPTY);
    push (STACK_OP2, EMPTY);
    push (STACK_OP3, EMPTY);
}

void test_output (void) {
    int p, o1, o2, o3;

    while ((p = get (STACK_OPCODE)) != EMPTY) {
        if ((p >= OP_CMP_EQ_REG_CONST) && (p <= OP_CMP_LE_REG_CONST)) {
            printf ("R%i %s %i\n", get (STACK_OP1), op_names [p], get(STACK_OP2));
            get (STACK_OP3);
        }
        else if (p == OP_ASSIGNMENT_REG_CONST) {
            printf ("R%i %s %i\n", get (STACK_OP1), op_names [p], get(STACK_OP2));
            get (STACK_OP3);
        }
        else {
            if ((p == OP_INC_REG_REG_CONST) || (p == OP_INC_REG_REG_REG) || (p == OP_DEC_REG_REG_CONST) || (p == OP_DEC_REG_REG_REG)) {
                printf ("R%i %s R%i %s\n", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p]);
                get (STACK_OP3);
            }
            else if ((p >= OP_ADD_REG_REG_CONST) && (p <= OP_EXOR_REG_REG_CONST))
                printf ("R%i %s R%i %s %i\n", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
            else
                printf ("R%i %s R%i %s R%i\n", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
        }
    }
}

int expr0 () {
    printf ("\\node [zbox] (z%i) {\\verb\"", 0);
    registr ();
    printf (" <- ");
    operand ();
    if ((rand () % RAND_EXPR_OPERATOR_OPERAND_FOLLOW) == 0) {
        operator ();
        operand ();
    }
    printf ("\"};\n");
return 0;
}


int expr (int z, int zs, int dir) {
    int p = get (STACK_OPCODE);
    printf ("&&&&%i %i\n", p, queue_ptr[STACK_OPCODE]);
    if (dir == NO) {
        printf ("\\node [zbox] (z%i) {\\verb\"", z);
    }
    else if (dir == WEST) {
        printf ("\\node [zbox, below=of z%i.west, yshift=-4em] (z%i) {\\verb\"", zs, z);
    }
    else if (dir == EAST) {
        printf ("\\node [zbox, below=of z%i.east, yshift=-4em] (z%i) {\\verb\"",zs, z);
    }
    if (p == OP_ASSIGNMENT_REG_CONST) {
            printf ("R%i %s %i", get (STACK_OP1), op_names [p], get(STACK_OP2));
            get (STACK_OP3);
    }
    else if ((p == OP_INC_REG_REG_CONST) || (p == OP_INC_REG_REG_REG) || (p == OP_DEC_REG_REG_CONST) || (p == OP_DEC_REG_REG_REG)) {
        printf ("R%i %s R%i %s", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p]);
        get (STACK_OP3);
    }
    else if ((p >= OP_ADD_REG_REG_CONST) && (p <= OP_EXOR_REG_REG_CONST))
        printf ("R%i %s R%i %s %i", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
    else {
        printf ("R%i %s R%i %s R%i", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
    }

   printf ("\"};\n");
    if (dir == NO) {
        printf ("\\draw [->] (z%i) -- (z%i);\n\n", zs, z);
    }
    else if (dir == WEST) {
        printf ("\\draw [->] (z%i.west) -- (z%i);\n\n", zs, z);
    }
    else if (dir == EAST) {
        printf ("\\draw [->] (z%i.east) -- (z%i);\n\n", zs, z);
    }

return z;
}

int cond (int z, int zs, int dir) {
    int p = get (STACK_OPCODE);
    if (dir == NO) {
        printf ("\\node [ebox] (z%i) {\\verb\"", z);
    }
    else if (dir == WEST) {
        printf ("\\node [ebox, below=of z%i.west, yshift=-4em] (z%i) {\\verb\"", zs, z);
    }
    else if (dir == EAST) {
        printf ("\\node [ebox, below=of z%i.east, yshift=-4em] (z%i) {\\verb\"",zs, z);
    }
    //printf ("\\node [ebox] (z%i) {\\verb\" ", z);
    printf ("R%i %s %i", get (STACK_OP1), op_names [p], get(STACK_OP2));
    get (STACK_OP3);
    printf ("\"};\n");
    if (dir == NO) {
        printf ("\\draw [->] (z%i) -- (z%i);\n\n", zs, z);
    }
    else if (dir == WEST) {
        printf ("\\draw [->] (z%i.west) -- (z%i);\n\n", zs, z);
    }
    else if (dir == EAST) {
        printf ("\\draw [->] (z%i.east) -- (z%i);\n\n", zs, z);
    }

    return z;
}


/*int as (int z, int zs, int dir) {
    int ztmp;
    int r;
    if ((r = (rand () % 8)) < 2) {
        z = ztmp = cond (z+1, z, dir);
        z = expr (z+1, ztmp, WEST);
        z = expr (z+1, z, NO);
        z = as (z, z, NO);
        z = expr (z+1, ztmp, EAST);
        z = expr (z+1, z, NO);
        z = as (z, z, NO);

    }
    else if ((r >= 2) && (r <= 5)) {
        ztmp = z;
        z = expr (z+1, ztmp, dir);
        as (z, ztmp, NO);
    }
return z;
}

*/

int as (int z, int zs, int dir) {
    int ztmp;
    int r, rtmp;

    if (((r = get (STACK_OPCODE)) >= OP_CMP_EQ_REG_CONST) && (r <= OP_CMP_LE_REG_CONST)){
        queue_ptr [STACK_OPCODE]--;
        z = ztmp = cond (z+1, z, dir);
        z = expr (z+1, ztmp, WEST);
        z = expr (z+1, z, NO);
        z = as (z, z, NO);
        z = expr (z+1, ztmp, EAST);
        z = expr (z+1, z, NO);
        z = as (z, z, NO);

    }
    else if (r != EMPTY) {
        queue_ptr [STACK_OPCODE]--;
        ztmp = z;
        z = expr (z+1, ztmp, dir);
        as (z, ztmp, NO);
    }
    else
        return z;
return z;
}






int main (void) {
    time_t t;
    int j;
    srand (t = time(NULL));
    //expr0();
    //as (0, 0, NO);
    init_stack ();
    queue_init ();
    init ();
    test_output ();
    queue_init ();
    as (0, 0, NO);
return 0;
}