/*
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;
}