/* 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 5 #define STD_PROGRAM2_N 4 FILE *fout = NULL; int lineelse [MAX_STATES]; int lineif [MAX_STATES]; int linegoto1 [MAX_STATES]; int linegoto2 [MAX_STATES]; int stateif = 0; int stateelse = 0; int stategoto1 = 0; int stategoto2 = 0; int stategotodst = 0; int gotodst [MAX_STATES]; int line = 0; int nline = 0; int maxstate = 0; char *opstr [] = {"+", "-", "<<", ">>", "\&\&", "||", "!"}; char *cmpstr [] = {"<=", ">=", "==", "!=", "<", ">"}; void operator (void); void cmp (void); void operand (void); void expr (int); void condition (int, int, int, int); void program (int, int, int, int); void program2 (int, int, int, int); void registr (void); void cnst (void); void operator (void); void printemptyspace (int); void printemptyspace (int n) { int i; for (i = 0; i < n*2; i++) fprintf (fout, " "); } void registr (void) { fprintf (fout, " %c ", (rand () % MAX_EXPR_REG_VAL) + FIRST_REG_VAL); return; } void cnst (void) { fprintf (fout, " %i ", rand () % MAX_EXPR_CONST_VAL); return; } void operator (void) { fprintf (fout, " %s ", opstr [rand () % MAX_EXPR_OPERATOR_VAL]); return; } void cmp (void) { fprintf (fout, " %s ", cmpstr [rand () % MAX_EXPR_CMP_OPERATOR_VAL]); return; } void operand (void) { if ((rand () % RAND_OPERAND_CONST_REGISTER) == 0) cnst (); else registr (); return; } void expr (int emptyspacen) { fprintf (fout, "%4i:", line++); printemptyspace (emptyspacen); registr (); fprintf (fout, " <- "); operand (); if ((rand () % RAND_EXPR_OPERATOR_OPERAND_FOLLOW) == 0) { operator (); operand (); } fprintf (fout, "n"); return; } void condition (int n, int i, int emptyspacen, int depth) { int goto1or2; goto1or2 = rand () % RAND_COND_TRUE_FALSE_DESICION; lineif [stateif++] = line; fprintf (fout, "%4i:", line++); printemptyspace (emptyspacen); fprintf (fout, " IF ", line); registr (); cmp (); operand (); fprintf (fout, " THEN n", line); program (n, i+1, emptyspacen+1, depth+1); linegoto1 [stategoto1++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen+1); if( goto1or2 ) fprintf (fout, " GOTO %in", lineif [gotodst[stategotodst++]]); else fprintf (fout, " GOTO %in", rand () % (nline+1)); lineelse [stateelse++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen); fprintf (fout, " ELSE n", line); program (n, i+1, emptyspacen+1, depth+1); linegoto2 [stategoto2++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen+1); if ( !goto1or2) fprintf (fout, " GOTO %in", lineif [gotodst[stategotodst++]]); else fprintf (fout, " GOTO %in", rand () % (nline+1)); fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen); fprintf (fout, " FI n", ' '); return; } void program2 (int n, int i, int emptyspacen, int depth) { if (((rand () % RAND_PROGRAM_COND_EXPR_DESICION) == 0)) expr (emptyspacen); if (i < n) { program2 (n, i+1, emptyspacen, depth); } return; } void program (int n, int i, int emptyspacen, int depth) { program2 (STD_PROGRAM2_N, 0, emptyspacen, depth); if ((i < n) \&\& (depth < IF_ELSE_DEPTH)) condition (n, i+1, emptyspacen, depth+1); return; } void connect (int n) { int i; int j; int t; gotodst [0] = rand () % n; for (i = 1; i < n; ) { t = rand () % n; for (j = 0; j < i; j++) { if (gotodst [j] == t) { t = rand () % n; j = 0; } } if (t != i) { gotodst [i] = t; i++; } } return; } int main (void) { time_t t; int j; srand (t = time(NULL)); fout = stderr; program (STD_PROGRAM_N, 0, 0, 0); maxstate = line; srand (t); fout = stdout; /*for (j = 0; j < stateif; j++) { fprintf (fout, "If %in", lineif [j]); fprintf (fout, "Else %in", lineelse [j]); fprintf (fout, "Goto 1 %in", linegoto1 [j]); fprintf (fout, "Goto 2 %in", linegoto2 [j]); }*/ if (stateif != 0) { connect (stateif); } nline = line; line = 0; stategotodst = 0; srand (t); program (STD_PROGRAM_N, 0, 0, 0); return 0; }
Zum generieren von Übungsaufgaben von ASM-Diagrammen. Ich erkläre gleich, welche Übungsaufgaben-Generatoren ich programmiert habe - nachher. Weil: Die Aufgaben sind alle von mir gemacht. Ich habe Programme geschrieben, damit ich das üben kann.
Die erste Version von dem ASM-Diagramm-Generator, was auf dem Prinzip von Parsern beruht, hatte Macken.
Etwa, das hinter der Bedingung noch Anweisungen stehen konnten. Nun kann man sich eine Bedingung als
IF ... THEN ... ELSE ... FI
vorstellen. Manch einer wird sich fragen: Wozu ist das gut? Dass ich
IF THEN ELSEbeantworten
Jetzt sind die Zustände mit Nummern versehen, die eindeutig sind
0 1 2 3 ...
Auf eine Bedingung folgt, ein Folgezustand, ausgedrückt mit
GOTO
Es folgt auf
JA
und das
NEIN
Es macht keinen Sinn, wenn wir die Nummern angucken
0 1 2 3 ...
Die ja, ohne Bedingung, ein Fluss sind, wenn auf ein
GOTO
Ein Block von Anweisungen, die die Reihenfolge der Zustände bedient, ein
JA
NEIN
JA
NEIN
Dann hätte die Bedingung ja drei Folgen. Wenn neben dem
JA
NEINNoch ein Block folgt, das
GOTOaber nicht dahin führt, haben wir einen verweisten Block.
0: b <- 39 >> 62 1: IF d >= 45 THEN 2: IF c == a THEN GOTO 3 ELSE 3: c <- 18 4: a <- 119 5: c <- 18 GOTO 2 FI GOTO 7 ELSE 6: a <- 50 7: IF c <= 109 THEN 8: c <- c - 14 GOTO 7 ELSE 9: c <- d 10: d <- c \&\& 14 GOTO 1 FI GOTO 4 FI
Und verbessert habe ich das:
Version 2:
Zeile 190 bis 197
void program (int n, int i, int emptyspacen, int depth) { program2 (STD_PROGRAM2_N, 0, emptyspacen, depth); if ((i < n) \&\& (depth < IF_ELSE_DEPTH)) { program (n, i+1, emptyspacen, depth+1); condition (n, i+1, emptyspacen, depth+1); } return; }
Zu, Version 3, Zeile 190 bis 195:
void program (int n, int i, int emptyspacen, int depth) { program2 (STD_PROGRAM2_N, 0, emptyspacen, depth); if ((i < n) \&\& (depth < IF_ELSE_DEPTH)) condition (n, i+1, emptyspacen, depth+1); return; }