Ich habe den Quelltext verbessert
[code]
/*
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 %i\n", lineif [gotodst[stategotodst++]]);
else
fprintf (fout, " GOTO %i\n", 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 %i\n", lineif [gotodst[stategotodst++]]);
else
fprintf (fout, " GOTO %i\n", 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 %i\n", lineif [j]);
fprintf (fout, "Else %i\n", lineelse [j]);
fprintf (fout, "Goto 1 %i\n", linegoto1 [j]);
fprintf (fout, "Goto 2 %i\n", linegoto2 [j]);
}*/
if (stateif != 0) {
connect (stateif);
}
nline = line;
line = 0;
stategotodst = 0;
srand (t);
program (STD_PROGRAM_N, 0, 0, 0);
return 0;
}
[/code]
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
[code]
IF ... THEN
...
ELSE
...
FI
[/code]
vorstellen. Manch einer wird sich fragen: Wozu ist das gut? Dass ich
[list=1]
[*] erstens: [code] IF THEN ELSE [/code] für ASM-Diagramme nehme, ASM-Diagramme sind ja extra so gezeichnet und jetzt diese Ausdrücke. Na ja, bedenken wir: Zeilennummerierung entspricht Zuständen. Ausserdem: Eine Bedinung, die entweder [code]TRUE ^= JA [/code] oder [code]FALSE ^= NEIN[/code] ist, kann ich auch mit [code] IF THEN ELSE [/code] beantworten
[*] Es geht nicht um das Zeichnen Lernen von ASM-Diagrammen. So gesehen macht das ja dann keinen Unterschied. Der Witz ist, dass man damit dann ein Mikroprogrammsteuerwerk zeichnen kann und ein Operationswerk. Also, man kann sehr schnell zum fertigen Steuer und Operationswerk kommen
[/list]
Jetzt sind die Zustände mit Nummern versehen, die eindeutig sind
[code]
0
1
2
3
...
[/code]
Auf eine Bedingung folgt, ein Folgezustand, ausgedrückt mit
[code]
GOTO
[/code]
Es folgt auf
[code]
JA
[/code]
und das
[code]
NEIN
[/code]
Es macht keinen Sinn, wenn wir die Nummern angucken
[code]
0
1
2
3
...
[/code]
Die ja, ohne Bedingung, ein Fluss sind, wenn auf ein
[code]
GOTO
[/code]
Ein Block von Anweisungen, die die Reihenfolge der Zustände bedient, ein
[code]
JA
[/code]
[code]
NEIN
[/code]
[list=1]
[*] [code]JA[/code]
[*] [code]NEIN[/code]
[*] Folgezustand
[/list]
Dann hätte die Bedingung ja drei Folgen. Wenn neben dem
[code]JA[/code]
[code]NEIN[/code]
Noch ein Block folgt, das
[code]GOTO[/code]
aber nicht dahin führt, haben wir einen verweisten Block.
Das war die Verbesserung Version 2 des Übungsprogramms. Jetzt ist bei der Korrektur allerdings wieder ein Fehler passiert, der war ganz schnell korrigiert. Jetzt folgen Bedingungen auf Bedingungen und das ist ebenso, wie wenn Zustände auf Bedingungen folgen. Das heisst am Ende kann es nur eine Bedingung geben. Hier ist das Beispiel, dass es funktioniert
[code]
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
[/code]
Und verbessert habe ich das:
Version 2:
Zeile 190 bis 197
[code]
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;
}
[/code]
Zu, Version 3, Zeile 190 bis 195:
[code]
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;
}
[/code]