/* 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 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; int realyusedstaten = 1; char *opstr [] = {"+", "-", "<<", ">>", "\&\&", "||", "!"}; char *cmpstr [] = {"<=", ">=", "==", "!=", "<", ">"}; void operator (void); void cmp (void); void operand (void); void expr (int); void condition (int, int, int, int); void condition2 (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; 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); fprintf (fout, " %4cn", ' '); 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); fprintf (fout, " %4cn", ' '); fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen); fprintf (fout, " FI n", ' '); return; } void condition2 (int n, int i, int emptyspacen, int depth) { int goto1or2; lineif [stateif++] = line; fprintf (fout, "%4i:", line++); printemptyspace (emptyspacen); fprintf (fout, " IF ", line); registr (); cmp (); operand (); fprintf (fout, " THEN n", line); program2 (n, i+1, emptyspacen+1, depth+1); linegoto1 [stategoto1++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen+1); fprintf (fout, " GOTO %in", lineif [gotodst[stategotodst++%(realyusedstaten)]]); lineelse [stateelse++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen); fprintf (fout, " ELSE n", line); program2 (n, i+1, emptyspacen+1, depth+1); linegoto2 [stategoto2++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen+1); fprintf (fout, " GOTO %in", lineif [gotodst[stategotodst++%(realyusedstaten)]]); 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 ((rand () % RAND_COND_END_OR_GO_ON) == 0) condition2 (n, i+1, emptyspacen, depth+1); else if ((i < n) \&\& (depth < IF_ELSE_DEPTH)) condition (n, i+1, emptyspacen, depth+1); else { linegoto1 [stategoto1++] = line; fprintf (fout, "%4c ", ' '); printemptyspace (emptyspacen); fprintf (fout, " GOTO %in", lineif [gotodst[stategotodst++%(realyusedstaten)]]); 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); realyusedstaten = stateif; } nline = line; line = 0; stategotodst = 0; srand (t); fprintf(stderr, "%i stategotodstn", stategotodst); fprintf(stderr, "%i stateifn", stateif); program (STD_PROGRAM_N, 0, 0, 0); return 0; }
/* expr ::= expr + term | term term ::= term * factor | factor factor ::= '(' expr ')' | const Bzw. expr ::= term | term '+' expr term ::= factor | factor '*' term factor ::= '(' expr ')' | const const ::= '9', '8', ..., '0' */ /* Lexer */ let i = 0; let s = "((4+5*(4+2))+1)*3"; function nexttoken () { return s [i++]; } function tokenback () { i--; } function expr () { let x; let y = 0; x = term (); if (nexttoken () == '+') { y = expr (); } else tokenback (); return x + y; } function term () { let x; let y = 1; x = factor (); if (nexttoken () == '*') y = term (); else tokenback (); return x * y; } function factor () { let s = nexttoken (); let x1 = parseInt (s); let x; if (s == '(') { x = expr (); if (nexttoken () != ')') throw new Error("Missing closing bracket"); } else if ((x1 >= 0) \&\& (x1 <= 9)) x = x1; else throw new Error("Unknown or wrong character"); return x; } console.log (expr ()); console.log (((4+5*(4+2))+1)*3);
Sorry, dass das so lange gedauert hat, eine Variable war falsch benannt
# expr ::= expr + term | term # term ::= term * factor | factor # factor ::= '(' expr ')' | const # Bzw. # expr ::= term | term '+' expr # term ::= factor | factor '*' term # factor ::= '(' expr ')' | const # const ::= '9', '8', ..., '0' i=0 s = "((4+5*(4+2))+1)*3"; def nexttoken (): global i j = i if i >= len(s): return 'e' i = i+1 return s[j] def tokenback (): global i i = i-1 def expr (): y = 0 x = term() s = nexttoken () if s == '+': y = expr() elif s == 'e': return x+y else: tokenback() return x+y def term (): y = 1 x = factor() s = nexttoken () if s == '*': y = term () elif s == 'e': return x*y else: tokenback() return x*y def factor (): s = nexttoken () if s.isdigit (): y = int(s) if s == '(': x = expr() if nexttoken () != ')': exit () elif s == 'e': return 0 elif (y >= 0) and (y <= 9): x = y else: exit () return x print(expr())
Diese Compiler habe ich selber geschrieben, entsprechend der Bakus-Naur Normalform ohne Linksrekursion - parsen sie arithmetische Terme. Zu Aussagen, kommen wir schnell - indem wir das
>==