https://www.davidvajda.de/viewtopic.php?p=1184#p1184">
/* expr ::= term | term + expr
* term ::= factor | factor * term
* factor ::= id | (expr)
*
* expr ::= term | term '|' expr
* term ::= factor | factor '*' term
* factor ::= ch | (expr)
*
* Wie wir sehen werden f"uhrt das nicht zum Ziel. Die Grammatik geht anders
*
* 1.) m"usste nach dem * auch ein | kommen k"onnen. Zur Not setzt man Klammern
*
* Aber der | Operator ist infix. Und der wiederholungsoperator ist Postfix - und hat nur einen Operanden
*
* Das heisst:
*
* expr ::= term | term '|' expr
* term ::= factor | factor '*'
* factor ::= id | (expr)
*/
/*
#include <stdio.h>
#include <stdlib.h>
char gettoken ();
void tokenback ();
void expr ();
void factor ();
void term ();
char matchexpr [] = "(((acasdasd|b)*)|c)|p";
int i = 0;
char gettoken () {
return matchexpr [i++];
}
void tokenback () {
i--;
}
void expr () {
term ();
if (gettoken () == '|')
expr ();
else
tokenback ();
return;
}
*/
/* Das geht nicht
void term () {
factor ();
if (gettoken () == '*')
term ();
else
tokenback ();
return;
}
*/
/*
void term () {
char ch;
factor ();
if ((ch = gettoken ()) == '*');
else if((ch >= 'a') \&\& (ch <= 'z')) {
tokenback ();
term ();
}
else
tokenback ();
return;
}
void factor () {
char ch = gettoken ();
if (ch == '(') {
expr ();
if (gettoken () != ')') {
fprintf (stderr, "Geschlossene Klammer vergessen");
exit (1);
}
}
else if ((ch >= 'a') \&\& (ch <= 'z'))
printf ("%cn", ch);
else {
fprintf (stderr, "Falsches Zeichen %c", ch);
exit (1);
}
return;
}
int main (void) {
expr ();
}
*/
/*
*
* Jetzt kommt der Automat. Jetzt m"ussen wir nachdenken, ohne Robert Sedgewick
* a 0 -> 0
* aa 0 -> 0
* aaa 0 -> 0 -> 0
* aaaa 0 -> 0 -> 0 -> 0
* a(a|b) 0 -> 0
* 0 -> 1
*
* Also, das erste, was wir merken, die Zeichen sind nicht unsere Zust"ande - also 'a' entspricht nicht 0 und 'b' 1
*
* a(a|b)* 0 -> 0
* 0 -> 1
* 0 -> 0 -> 0
* 0 -> 1 -> 0
* 0 -> 0 -> 1
* 0 -> 1 -> 1
*
* Also, wenn man das hintereinander schreibt
*
* a(a|b)* Da ist mir das aufgefallen
*
* Sagen wir
* abc
* dann ist a nicht der Zustand, aber es steht an Index 0
* b steht an Index 1
* c an Index 2
* Gut, der Witz bei den Automaten, es kann der eine Zustand folgen, oder der anderen. Deswegen brauchen wir einen Automaten
* Das ist logisch. wenn ich 10 Zust"ande Folgezust"ande haben k"onnte, kann ich das nach der Baumregel, auf zwei Folgezust"ande reduzieren
*
* state1 [0] = 1
* state2 [0] = 1
* state1 [1] = 2
* state2 [1] = 2
* ...
*
* So w"are das bei einer Zeichenkette wie
*
* abc
*
* Jetzt angenommen ich habe ein ODER dann kommt
*
* state1 [5] = 1
* state2 [5] = 4
*
* Ich weiss wie es geht! Bingo!
*
* Es ist ganz einfach
*
* Ich habe die States
*
* state1 [...]
* state2 [...]
*
* daneben habe ich noch etwas. Ein Feld, was f"ur jeden Zustand angibt, was das f"ur ein Zeichen ist. Das ist was anderes. Also ein Feld
*
* statechar [...]
* Dann habe ich
*
* state1 [...]
* state2 [...]
* statechar [...]
*
* Jetzt muss ich mir merken
*
* "abcd"
*
* state1 [0] = 1
* state2 [0] = 1
* state1 [1] = 2
* state2 [1] = 2
* state1 [2] = 3
* state2 [2] = 3
* ...
*
* Nebenbei ist
*
* statechar [0] = 'a'
* ...
*
* Gut, das wichtige ist, bei ODER das hat nichts mit dem Zeichen zu tun
*
* Wenn da steht
* a(a|b)
*
* Dann folgt auf
* state1[0] = 1
* state2[0] = 2
*
* Bei einer Wiederholung folgt auf
*
* a*b
*
* state1 [0] = 0
* state2 [0] = 1
*
* Jetzt merken wir, die Grammatik ist Falsches
*
* Weil bei arithmetischen Ausdrucken, folgt auf Operand Operator Operand
* Und jetzt haben wir Operand Operand
*
* Dann f"uhren wir noch eine Regel eine
*
*
* expr ::= term | term '|' expr
* term ::= factor | factor term | factor*
* factor ::= id | (expr)
*
* Das hat mit dem Automaten nichts zu tun. Unabh"angig ob das eine Wiederholung oder ein ODER ist, tut der Automat
*
* Bei einer Wiederholung zeigt der Zustand auf sich selber. Bei einem ODER zeigt der Vorg"angezustand entweder auf den Einen Zustand oder den anderen. Das sind aber Folgezust"ande
*
* */
#include <stdio.h>
#include <stdlib.h>
char gettoken ();
void tokenback ();
char matchexpr [] = "((((acasdasd|b)*)|c)|p)|l";
//char matchexpr [] = "qbc|defg";
int i = 0;
int j = 0;
int state1 [128];
int state2 [128];
char statechar [1024];
char gettoken () {
return matchexpr [i++];
}
void tokenback () {
i--;
}
/* Das einfachste: Auf zeichen folgt Zeichen
*
*
* chr ::= ch | ch chr
* a
* aa
* aaa
*
* chr ::= rpt | rpt chr
* rpt ::= ch | *ch
*
* chr ::= sel | sel chr
* sel ::= rpt | + rpt sel // + rpt rpt
* rpt ::= ch | *ch
* ch ::= id | (chr)
*
* chr ::= sel | sel chr
* sel ::= rpt | rpt + sel // + rpt rpt
* rpt ::= ch | ch*
* ch ::= id | (chr)
*
* chr ::= expr | expr chr
* expr ::= term | term '|' expr
* term ::= factor | factor*
* factor ::= id | (expr)
* chr ::= expr | expr chr
* expr ::= term | term '|' term
* term ::= factor | factor*
* factor ::= id | (expr)
* */
int chr ();
int expr ();
int term ();
int factor ();
int chr () {
int ch;
expr ();
ch = gettoken ();
if ((ch >= 'a') \&\& (ch <= 'z')) {
tokenback ();
chr ();
}
else
tokenback();
}
int expr () {
term ();
if (gettoken () == '|')
term ();
else
tokenback ();
}
int term () {
factor ();
if (gettoken () == '*');
else
tokenback ();
}
int factor () {
int ch = gettoken ();
if (ch == '(') {
chr ();
if (gettoken () != ')') {
printf ("Klammer schliessen vergessen");
exit (1);
}
}
else if ((ch >= 'a') | (ch <= 'z'))
printf ("%cn", ch);
else {
printf ("Unbekanntes Zeichen");
exit (1);
}
}
int main (void) {
int k;
chr ();
}